diff options
325 files changed, 9035 insertions, 9677 deletions
diff --git a/Documentation/RCU/trace.txt b/Documentation/RCU/trace.txt index 187bbf10c92..8608fd85e92 100644 --- a/Documentation/RCU/trace.txt +++ b/Documentation/RCU/trace.txt @@ -1,185 +1,10 @@  CONFIG_RCU_TRACE debugfs Files and Formats -The rcupreempt and rcutree implementations of RCU provide debugfs trace -output that summarizes counters and state.  This information is useful for -debugging RCU itself, and can sometimes also help to debug abuses of RCU. -Note that the rcuclassic implementation of RCU does not provide debugfs -trace output. - -The following sections describe the debugfs files and formats for -preemptable RCU (rcupreempt) and hierarchical RCU (rcutree). - - -Preemptable RCU debugfs Files and Formats - -This implementation of RCU provides three debugfs files under the -top-level directory RCU: rcu/rcuctrs (which displays the per-CPU -counters used by preemptable RCU) rcu/rcugp (which displays grace-period -counters), and rcu/rcustats (which internal counters for debugging RCU). - -The output of "cat rcu/rcuctrs" looks as follows: - -CPU last cur F M -  0    5  -5 0 0 -  1   -1   0 0 0 -  2    0   1 0 0 -  3    0   1 0 0 -  4    0   1 0 0 -  5    0   1 0 0 -  6    0   2 0 0 -  7    0  -1 0 0 -  8    0   1 0 0 -ggp = 26226, state = waitzero - -The per-CPU fields are as follows: - -o	"CPU" gives the CPU number.  Offline CPUs are not displayed. - -o	"last" gives the value of the counter that is being decremented -	for the current grace period phase.  In the example above, -	the counters sum to 4, indicating that there are still four -	RCU read-side critical sections still running that started -	before the last counter flip. - -o	"cur" gives the value of the counter that is currently being -	both incremented (by rcu_read_lock()) and decremented (by -	rcu_read_unlock()).  In the example above, the counters sum to -	1, indicating that there is only one RCU read-side critical section -	still running that started after the last counter flip. - -o	"F" indicates whether RCU is waiting for this CPU to acknowledge -	a counter flip.  In the above example, RCU is not waiting on any, -	which is consistent with the state being "waitzero" rather than -	"waitack". - -o	"M" indicates whether RCU is waiting for this CPU to execute a -	memory barrier.  In the above example, RCU is not waiting on any, -	which is consistent with the state being "waitzero" rather than -	"waitmb". - -o	"ggp" is the global grace-period counter. - -o	"state" is the RCU state, which can be one of the following: - -	o	"idle": there is no grace period in progress. - -	o	"waitack": RCU just incremented the global grace-period -		counter, which has the effect of reversing the roles of -		the "last" and "cur" counters above, and is waiting for -		all the CPUs to acknowledge the flip.  Once the flip has -		been acknowledged, CPUs will no longer be incrementing -		what are now the "last" counters, so that their sum will -		decrease monotonically down to zero. - -	o	"waitzero": RCU is waiting for the sum of the "last" counters -		to decrease to zero. - -	o	"waitmb": RCU is waiting for each CPU to execute a memory -		barrier, which ensures that instructions from a given CPU's -		last RCU read-side critical section cannot be reordered -		with instructions following the memory-barrier instruction. - -The output of "cat rcu/rcugp" looks as follows: - -oldggp=48870  newggp=48873 - -Note that reading from this file provokes a synchronize_rcu().  The -"oldggp" value is that of "ggp" from rcu/rcuctrs above, taken before -executing the synchronize_rcu(), and the "newggp" value is also the -"ggp" value, but taken after the synchronize_rcu() command returns. - - -The output of "cat rcu/rcugp" looks as follows: - -na=1337955 nl=40 wa=1337915 wl=44 da=1337871 dl=0 dr=1337871 di=1337871 -1=50989 e1=6138 i1=49722 ie1=82 g1=49640 a1=315203 ae1=265563 a2=49640 -z1=1401244 ze1=1351605 z2=49639 m1=5661253 me1=5611614 m2=49639 - -These are counters tracking internal preemptable-RCU events, however, -some of them may be useful for debugging algorithms using RCU.  In -particular, the "nl", "wl", and "dl" values track the number of RCU -callbacks in various states.  The fields are as follows: - -o	"na" is the total number of RCU callbacks that have been enqueued -	since boot. - -o	"nl" is the number of RCU callbacks waiting for the previous -	grace period to end so that they can start waiting on the next -	grace period. - -o	"wa" is the total number of RCU callbacks that have started waiting -	for a grace period since boot.  "na" should be roughly equal to -	"nl" plus "wa". - -o	"wl" is the number of RCU callbacks currently waiting for their -	grace period to end. - -o	"da" is the total number of RCU callbacks whose grace periods -	have completed since boot.  "wa" should be roughly equal to -	"wl" plus "da". - -o	"dr" is the total number of RCU callbacks that have been removed -	from the list of callbacks ready to invoke.  "dr" should be roughly -	equal to "da". - -o	"di" is the total number of RCU callbacks that have been invoked -	since boot.  "di" should be roughly equal to "da", though some -	early versions of preemptable RCU had a bug so that only the -	last CPU's count of invocations was displayed, rather than the -	sum of all CPU's counts. - -o	"1" is the number of calls to rcu_try_flip().  This should be -	roughly equal to the sum of "e1", "i1", "a1", "z1", and "m1" -	described below.  In other words, the number of times that -	the state machine is visited should be equal to the sum of the -	number of times that each state is visited plus the number of -	times that the state-machine lock acquisition failed. - -o	"e1" is the number of times that rcu_try_flip() was unable to -	acquire the fliplock. - -o	"i1" is the number of calls to rcu_try_flip_idle(). - -o	"ie1" is the number of times rcu_try_flip_idle() exited early -	due to the calling CPU having no work for RCU. - -o	"g1" is the number of times that rcu_try_flip_idle() decided -	to start a new grace period.  "i1" should be roughly equal to -	"ie1" plus "g1". - -o	"a1" is the number of calls to rcu_try_flip_waitack(). - -o	"ae1" is the number of times that rcu_try_flip_waitack() found -	that at least one CPU had not yet acknowledge the new grace period -	(AKA "counter flip"). - -o	"a2" is the number of time rcu_try_flip_waitack() found that -	all CPUs had acknowledged.  "a1" should be roughly equal to -	"ae1" plus "a2".  (This particular output was collected on -	a 128-CPU machine, hence the smaller-than-usual fraction of -	calls to rcu_try_flip_waitack() finding all CPUs having already -	acknowledged.) - -o	"z1" is the number of calls to rcu_try_flip_waitzero(). - -o	"ze1" is the number of times that rcu_try_flip_waitzero() found -	that not all of the old RCU read-side critical sections had -	completed. - -o	"z2" is the number of times that rcu_try_flip_waitzero() finds -	the sum of the counters equal to zero, in other words, that -	all of the old RCU read-side critical sections had completed. -	The value of "z1" should be roughly equal to "ze1" plus -	"z2". - -o	"m1" is the number of calls to rcu_try_flip_waitmb(). - -o	"me1" is the number of times that rcu_try_flip_waitmb() finds -	that at least one CPU has not yet executed a memory barrier. - -o	"m2" is the number of times that rcu_try_flip_waitmb() finds that -	all CPUs have executed a memory barrier. +The rcutree implementation of RCU provides debugfs trace output that +summarizes counters and state.  This information is useful for debugging +RCU itself, and can sometimes also help to debug abuses of RCU. +The following sections describe the debugfs files and formats.  Hierarchical RCU debugfs Files and Formats @@ -210,9 +35,10 @@ rcu_bh:    6 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=859/1 dn=0 df=15 of=0 ri=0 ql=0 b=10    7 c=-275 g=-275 pq=1 pqc=-275 qp=0 dt=3761/1 dn=0 df=15 of=0 ri=0 ql=0 b=10 -The first section lists the rcu_data structures for rcu, the second for -rcu_bh.  Each section has one line per CPU, or eight for this 8-CPU system. -The fields are as follows: +The first section lists the rcu_data structures for rcu_sched, the second +for rcu_bh.  Note that CONFIG_TREE_PREEMPT_RCU kernels will have an +additional section for rcu_preempt.  Each section has one line per CPU, +or eight for this 8-CPU system.  The fields are as follows:  o	The number at the beginning of each line is the CPU number.  	CPUs numbers followed by an exclamation mark are offline, @@ -223,9 +49,9 @@ o	The number at the beginning of each line is the CPU number.  o	"c" is the count of grace periods that this CPU believes have  	completed.  CPUs in dynticks idle mode may lag quite a ways -	behind, for example, CPU 4 under "rcu" above, which has slept -	through the past 25 RCU grace periods.	It is not unusual to -	see CPUs lagging by thousands of grace periods. +	behind, for example, CPU 4 under "rcu_sched" above, which has +	slept through the past 25 RCU grace periods.  It is not unusual +	to see CPUs lagging by thousands of grace periods.  o	"g" is the count of grace periods that this CPU believes have  	started.  Again, CPUs in dynticks idle mode may lag behind. @@ -308,8 +134,10 @@ The output of "cat rcu/rcugp" looks as follows:  rcu_sched: completed=33062  gpnum=33063  rcu_bh: completed=464  gpnum=464 -Again, this output is for both "rcu" and "rcu_bh".  The fields are -taken from the rcu_state structure, and are as follows: +Again, this output is for both "rcu_sched" and "rcu_bh".  Note that +kernels built with CONFIG_TREE_PREEMPT_RCU will have an additional +"rcu_preempt" line.  The fields are taken from the rcu_state structure, +and are as follows:  o	"completed" is the number of grace periods that have completed.  	It is comparable to the "c" field from rcu/rcudata in that a @@ -324,23 +152,24 @@ o	"gpnum" is the number of grace periods that have started.  It is  	If these two fields are equal (as they are for "rcu_bh" above),  	then there is no grace period in progress, in other words, RCU  	is idle.  On the other hand, if the two fields differ (as they -	do for "rcu" above), then an RCU grace period is in progress. +	do for "rcu_sched" above), then an RCU grace period is in progress.  The output of "cat rcu/rcuhier" looks as follows, with very long lines: -c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 -1/1 0:127 ^0     -3/3 0:35 ^0    0/0 36:71 ^1    0/0 72:107 ^2    0/0 108:127 ^3     -3/3f 0:5 ^0    2/3 6:11 ^1    0/0 12:17 ^2    0/0 18:23 ^3    0/0 24:29 ^4    0/0 30:35 ^5    0/0 36:41 ^0    0/0 42:47 ^1    0/0 48:53 ^2    0/0 54:59 ^3    0/0 60:65 ^4    0/0 66:71 ^5    0/0 72:77 ^0    0/0 78:83 ^1    0/0 84:89 ^2    0/0 90:95 ^3    0/0 96:101 ^4    0/0 102:107 ^5    0/0 108:113 ^0    0/0 114:119 ^1    0/0 120:125 ^2    0/0 126:127 ^3     +c=6902 g=6903 s=2 jfq=3 j=72c7 nfqs=13142/nfqsng=0(13142) fqlh=6 oqlen=0 +1/1 .>. 0:127 ^0     +3/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3     +3/3f .>. 0:5 ^0    2/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3      rcu_bh: -c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 -0/1 0:127 ^0     -0/3 0:35 ^0    0/0 36:71 ^1    0/0 72:107 ^2    0/0 108:127 ^3     -0/3f 0:5 ^0    0/3 6:11 ^1    0/0 12:17 ^2    0/0 18:23 ^3    0/0 24:29 ^4    0/0 30:35 ^5    0/0 36:41 ^0    0/0 42:47 ^1    0/0 48:53 ^2    0/0 54:59 ^3    0/0 60:65 ^4    0/0 66:71 ^5    0/0 72:77 ^0    0/0 78:83 ^1    0/0 84:89 ^2    0/0 90:95 ^3    0/0 96:101 ^4    0/0 102:107 ^5    0/0 108:113 ^0    0/0 114:119 ^1    0/0 120:125 ^2    0/0 126:127 ^3 +c=-226 g=-226 s=1 jfq=-5701 j=72c7 nfqs=88/nfqsng=0(88) fqlh=0 oqlen=0 +0/1 .>. 0:127 ^0     +0/3 .>. 0:35 ^0    0/0 .>. 36:71 ^1    0/0 .>. 72:107 ^2    0/0 .>. 108:127 ^3     +0/3f .>. 0:5 ^0    0/3 .>. 6:11 ^1    0/0 .>. 12:17 ^2    0/0 .>. 18:23 ^3    0/0 .>. 24:29 ^4    0/0 .>. 30:35 ^5    0/0 .>. 36:41 ^0    0/0 .>. 42:47 ^1    0/0 .>. 48:53 ^2    0/0 .>. 54:59 ^3    0/0 .>. 60:65 ^4    0/0 .>. 66:71 ^5    0/0 .>. 72:77 ^0    0/0 .>. 78:83 ^1    0/0 .>. 84:89 ^2    0/0 .>. 90:95 ^3    0/0 .>. 96:101 ^4    0/0 .>. 102:107 ^5    0/0 .>. 108:113 ^0    0/0 .>. 114:119 ^1    0/0 .>. 120:125 ^2    0/0 .>. 126:127 ^3 -This is once again split into "rcu" and "rcu_bh" portions.  The fields are -as follows: +This is once again split into "rcu_sched" and "rcu_bh" portions, +and CONFIG_TREE_PREEMPT_RCU kernels will again have an additional +"rcu_preempt" section.  The fields are as follows:  o	"c" is exactly the same as "completed" under rcu/rcugp. @@ -372,6 +201,11 @@ o	"fqlh" is the number of calls to force_quiescent_state() that  	exited immediately (without even being counted in nfqs above)  	due to contention on ->fqslock. +o	"oqlen" is the number of callbacks on the "orphan" callback +	list.  RCU callbacks are placed on this list by CPUs going +	offline, and are "adopted" either by the CPU helping the outgoing +	CPU or by the next rcu_barrier*() call, whichever comes first. +  o	Each element of the form "1/1 0:127 ^0" represents one struct  	rcu_node.  Each line represents one level of the hierarchy, from  	root to leaves.  It is best to think of the rcu_data structures @@ -379,7 +213,7 @@ o	Each element of the form "1/1 0:127 ^0" represents one struct  	might be either one, two, or three levels of rcu_node structures,  	depending on the relationship between CONFIG_RCU_FANOUT and  	CONFIG_NR_CPUS. -	 +  	o	The numbers separated by the "/" are the qsmask followed  		by the qsmaskinit.  The qsmask will have one bit  		set for each entity in the next lower level that @@ -389,10 +223,19 @@ o	Each element of the form "1/1 0:127 ^0" represents one struct  		The value of qsmaskinit is assigned to that of qsmask  		at the beginning of each grace period. -		For example, for "rcu", the qsmask of the first entry -		of the lowest level is 0x14, meaning that we are still -		waiting for CPUs 2 and 4 to check in for the current -		grace period. +		For example, for "rcu_sched", the qsmask of the first +		entry of the lowest level is 0x14, meaning that we +		are still waiting for CPUs 2 and 4 to check in for the +		current grace period. + +	o	The characters separated by the ">" indicate the state +		of the blocked-tasks lists.  A "T" preceding the ">" +		indicates that at least one task blocked in an RCU +		read-side critical section blocks the current grace +		period, while a "." preceding the ">" indicates otherwise. +		The character following the ">" indicates similarly for +		the next grace period.  A "T" should appear in this +		field only for rcu-preempt.  	o	The numbers separated by the ":" are the range of CPUs  		served by this struct rcu_node.  This can be helpful @@ -431,8 +274,9 @@ rcu_bh:    6 np=120834 qsp=9902 cbr=0 cng=0 gpc=6 gps=3 nf=2 nn=110921    7 np=144888 qsp=26336 cbr=0 cng=0 gpc=8 gps=2 nf=0 nn=118542 -As always, this is once again split into "rcu" and "rcu_bh" portions. -The fields are as follows: +As always, this is once again split into "rcu_sched" and "rcu_bh" +portions, with CONFIG_TREE_PREEMPT_RCU kernels having an additional +"rcu_preempt" section.  The fields are as follows:  o	"np" is the number of times that __rcu_pending() has been invoked  	for the corresponding flavor of RCU. diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index e41a7fecf0d..d542ca243b8 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -830,7 +830,7 @@ sched:	Critical sections	Grace period		Barrier  SRCU:	Critical sections	Grace period		Barrier  	srcu_read_lock		synchronize_srcu	N/A -	srcu_read_unlock +	srcu_read_unlock	synchronize_srcu_expedited  SRCU:	Initialization/cleanup  	init_srcu_struct diff --git a/Documentation/dontdiff b/Documentation/dontdiff index e1efc400bed..e151b2a3626 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -65,6 +65,7 @@ aicdb.h*  asm-offsets.h  asm_offsets.h  autoconf.h* +av_permissions.h  bbootsect  bin2c  binkernel.spec @@ -95,12 +96,14 @@ docproc  elf2ecoff  elfconfig.h*  fixdep +flask.h  fore200e_mkfirm  fore200e_pca_fw.c*  gconf  gen-devlist  gen_crc32table  gen_init_cpio +genheaders  genksyms  *_gray256.c  ihex2fw diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 52c34b4f567..d8ce217d1f7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -85,7 +85,6 @@ parameter is applicable:  	PPT	Parallel port support is enabled.  	PS2	Appropriate PS/2 support is enabled.  	RAM	RAM disk support is enabled. -	ROOTPLUG The example Root Plug LSM is enabled.  	S390	S390 architecture is enabled.  	SCSI	Appropriate SCSI support is enabled.  			A lot of drivers has their options described inside of @@ -779,6 +778,13 @@ and is between 256 and 4096 characters. It is defined in the file  			by the set_ftrace_notrace file in the debugfs  			tracing directory. +	ftrace_graph_filter=[function-list] +			[FTRACE] Limit the top level callers functions traced +			by the function graph tracer at boot up. +			function-list is a comma separated list of functions +			that can be changed at run time by the +			set_graph_function file in the debugfs tracing directory. +  	gamecon.map[2|3]=  			[HW,JOY] Multisystem joystick and NES/SNES/PSX pad  			support via parallel port (up to 5 devices per port) @@ -2032,8 +2038,15 @@ and is between 256 and 4096 characters. It is defined in the file  	print-fatal-signals=  			[KNL] debug: print fatal signals -			print-fatal-signals=1: print segfault info to -			the kernel console. + +			If enabled, warn about various signal handling +			related application anomalies: too many signals, +			too many POSIX.1 timers, fatal signals causing a +			coredump - etc. + +			If you hit the warning due to signal overflow, +			you might want to try "ulimit -i unlimited". +  			default: off.  	printk.time=	Show timing data prefixed to each printk message line @@ -2164,15 +2177,6 @@ and is between 256 and 4096 characters. It is defined in the file  			Useful for devices that are detected asynchronously  			(e.g. USB and MMC devices). -	root_plug.vendor_id= -			[ROOTPLUG] Override the default vendor ID - -	root_plug.product_id= -			[ROOTPLUG] Override the default product ID - -	root_plug.debug= -			[ROOTPLUG] Enable debugging output -  	rw		[KNL] Mount root device read-write on boot  	S		[KNL] Run init in single mode diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt index 059934363ca..446f43b309d 100644 --- a/Documentation/pcmcia/driver-changes.txt +++ b/Documentation/pcmcia/driver-changes.txt @@ -1,5 +1,17 @@  This file details changes in 2.6 which affect PCMCIA card driver authors: +* no cs_error / CS_CHECK / CONFIG_PCMCIA_DEBUG (as of 2.6.33) +   Instead of the cs_error() callback or the CS_CHECK() macro, please use +   Linux-style checking of return values, and -- if necessary -- debug +   messages using "dev_dbg()" or "pr_debug()". + +* New CIS tuple access (as of 2.6.33) +   Instead of pcmcia_get_{first,next}_tuple(), pcmcia_get_tuple_data() and +   pcmcia_parse_tuple(), a driver shall use "pcmcia_get_tuple()" if it is +   only interested in one (raw) tuple, or "pcmcia_loop_tuple()" if it is +   interested in all tuples of one type. To decode the MAC from CISTPL_FUNCE, +   a new helper "pcmcia_get_mac_from_cis()" was added. +  * New configuration loop helper (as of 2.6.28)     By calling pcmcia_loop_config(), a driver can iterate over all available     configuration options. During a driver's probe() phase, one doesn't need diff --git a/Documentation/trace/ftrace-design.txt b/Documentation/trace/ftrace-design.txt index 7003e10f10f..641a1ef2a7f 100644 --- a/Documentation/trace/ftrace-design.txt +++ b/Documentation/trace/ftrace-design.txt @@ -213,10 +213,19 @@ If you can't trace NMI functions, then skip this option.  <details to be filled> -HAVE_FTRACE_SYSCALLS +HAVE_SYSCALL_TRACEPOINTS  --------------------- -<details to be filled> +You need very few things to get the syscalls tracing in an arch. + +- Have a NR_syscalls variable in <asm/unistd.h> that provides the number +  of syscalls supported by the arch. +- Implement arch_syscall_addr() that resolves a syscall address from a +  syscall number. +- Support the TIF_SYSCALL_TRACEPOINT thread flags +- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace +  in the ptrace syscalls tracing path. +- Tag this arch as HAVE_SYSCALL_TRACEPOINTS.  HAVE_FTRACE_MCOUNT_RECORD diff --git a/MAINTAINERS b/MAINTAINERS index 1186b1978b2..89ceb4005c5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3023,11 +3023,8 @@ S:	Maintained  F:	fs/autofs4/  KERNEL BUILD -M:	Sam Ravnborg <sam@ravnborg.org> -T:	git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-next.git -T:	git git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fixes.git  L:	linux-kbuild@vger.kernel.org -S:	Maintained +S:	Orphan  F:	Documentation/kbuild/  F:	Makefile  F:	scripts/Makefile.* @@ -1,7 +1,7 @@  VERSION = 2  PATCHLEVEL = 6  SUBLEVEL = 32 -EXTRAVERSION = -rc8 +EXTRAVERSION =  NAME = Man-Eating Seals of Antiquity  # *DOCUMENTATION* @@ -379,6 +379,7 @@ export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exc  PHONY += scripts_basic  scripts_basic:  	$(Q)$(MAKE) $(build)=scripts/basic +	$(Q)rm -f .tmp_quiet_recordmcount  # To avoid any implicit rule to kick in, define an empty command.  scripts/basic/%: scripts_basic ; diff --git a/arch/avr32/include/asm/bug.h b/arch/avr32/include/asm/bug.h index 331d45bab18..2aa373cc61b 100644 --- a/arch/avr32/include/asm/bug.h +++ b/arch/avr32/include/asm/bug.h @@ -52,7 +52,7 @@  #define BUG()								\  	do {								\  		_BUG_OR_WARN(0);					\ -		for (;;);						\ +		unreachable();						\  	} while (0)  #define WARN_ON(condition)							\ diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h index dcbaea7ce12..f0acde68aae 100644 --- a/arch/ia64/include/asm/swiotlb.h +++ b/arch/ia64/include/asm/swiotlb.h @@ -4,8 +4,6 @@  #include <linux/dma-mapping.h>  #include <linux/swiotlb.h> -extern int swiotlb_force; -  #ifdef CONFIG_SWIOTLB  extern int swiotlb;  extern void pci_swiotlb_init(void); diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c index 285aae8431c..53292abf846 100644 --- a/arch/ia64/kernel/pci-swiotlb.c +++ b/arch/ia64/kernel/pci-swiotlb.c @@ -41,7 +41,7 @@ struct dma_map_ops swiotlb_dma_ops = {  void __init swiotlb_dma_init(void)  {  	dma_ops = &swiotlb_dma_ops; -	swiotlb_init(); +	swiotlb_init(1);  }  void __init pci_swiotlb_init(void) @@ -51,7 +51,7 @@ void __init pci_swiotlb_init(void)  		swiotlb = 1;  		printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");  		machvec_init("dig"); -		swiotlb_init(); +		swiotlb_init(1);  		dma_ops = &swiotlb_dma_ops;  #else  		panic("Unable to find Intel IOMMU"); diff --git a/arch/mips/include/asm/bug.h b/arch/mips/include/asm/bug.h index 6cf29c26e87..540c98a810d 100644 --- a/arch/mips/include/asm/bug.h +++ b/arch/mips/include/asm/bug.h @@ -11,9 +11,7 @@  static inline void __noreturn BUG(void)  {  	__asm__ __volatile__("break %0" : : "i" (BRK_BUG)); -	/* Fool GCC into thinking the function doesn't return. */ -	while (1) -		; +	unreachable();  }  #define HAVE_ARCH_BUG diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index 3fe1fcfa2e7..fe0d7980560 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c @@ -306,6 +306,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,  	if (cpu_has_llsc && R10000_LLSC_WAR) {  		__asm__ __volatile__ ( +		"	.set	mips3					\n"  		"	li	%[err], 0				\n"  		"1:	ll	%[old], (%[addr])			\n"  		"	move	%[tmp], %[new]				\n" @@ -320,6 +321,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,  		"	"STR(PTR)"	1b, 4b				\n"  		"	"STR(PTR)"	2b, 4b				\n"  		"	.previous					\n" +		"	.set	mips0					\n"  		: [old] "=&r" (old),  		  [err] "=&r" (err),  		  [tmp] "=&r" (tmp) @@ -329,6 +331,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,  		: "memory");  	} else if (cpu_has_llsc) {  		__asm__ __volatile__ ( +		"	.set	mips3					\n"  		"	li	%[err], 0				\n"  		"1:	ll	%[old], (%[addr])			\n"  		"	move	%[tmp], %[new]				\n" @@ -347,6 +350,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,  		"	"STR(PTR)"	1b, 5b				\n"  		"	"STR(PTR)"	2b, 5b				\n"  		"	.previous					\n" +		"	.set	mips0					\n"  		: [old] "=&r" (old),  		  [err] "=&r" (err),  		  [tmp] "=&r" (tmp) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 9f40e1ff9b4..041fc1afc3f 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -110,7 +110,6 @@ static struct korina_device korina_dev0_data = {  static struct platform_device korina_dev0 = {  	.id = -1,  	.name = "korina", -	.dev.driver_data = &korina_dev0_data,  	.resource = korina_dev0_res,  	.num_resources = ARRAY_SIZE(korina_dev0_res),  }; @@ -332,6 +331,8 @@ static int __init plat_setup_devices(void)  	/* set the uart clock to the current cpu frequency */  	rb532_uart_res[0].uartclk = idt_cpu_freq; +	dev_set_drvdata(&korina_dev0.dev, &korina_dev0_data); +  	return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs));  } diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 53bcf3d792d..b152de3e64d 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -345,7 +345,7 @@ void __init setup_arch(char **cmdline_p)  #ifdef CONFIG_SWIOTLB  	if (ppc_swiotlb_enable) -		swiotlb_init(); +		swiotlb_init(1);  #endif  	paging_init(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 04f638d82fb..df2c9e932b3 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -550,7 +550,7 @@ void __init setup_arch(char **cmdline_p)  #ifdef CONFIG_SWIOTLB  	if (ppc_swiotlb_enable) -		swiotlb_init(); +		swiotlb_init(1);  #endif  	paging_init(); diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 43c0acad716..16c673096a2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -95,6 +95,34 @@ config S390  	select HAVE_ARCH_TRACEHOOK  	select INIT_ALL_POSSIBLE  	select HAVE_PERF_EVENTS +	select ARCH_INLINE_SPIN_TRYLOCK +	select ARCH_INLINE_SPIN_TRYLOCK_BH +	select ARCH_INLINE_SPIN_LOCK +	select ARCH_INLINE_SPIN_LOCK_BH +	select ARCH_INLINE_SPIN_LOCK_IRQ +	select ARCH_INLINE_SPIN_LOCK_IRQSAVE +	select ARCH_INLINE_SPIN_UNLOCK +	select ARCH_INLINE_SPIN_UNLOCK_BH +	select ARCH_INLINE_SPIN_UNLOCK_IRQ +	select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE +	select ARCH_INLINE_READ_TRYLOCK +	select ARCH_INLINE_READ_LOCK +	select ARCH_INLINE_READ_LOCK_BH +	select ARCH_INLINE_READ_LOCK_IRQ +	select ARCH_INLINE_READ_LOCK_IRQSAVE +	select ARCH_INLINE_READ_UNLOCK +	select ARCH_INLINE_READ_UNLOCK_BH +	select ARCH_INLINE_READ_UNLOCK_IRQ +	select ARCH_INLINE_READ_UNLOCK_IRQRESTORE +	select ARCH_INLINE_WRITE_TRYLOCK +	select ARCH_INLINE_WRITE_LOCK +	select ARCH_INLINE_WRITE_LOCK_BH +	select ARCH_INLINE_WRITE_LOCK_IRQ +	select ARCH_INLINE_WRITE_LOCK_IRQSAVE +	select ARCH_INLINE_WRITE_UNLOCK +	select ARCH_INLINE_WRITE_UNLOCK_BH +	select ARCH_INLINE_WRITE_UNLOCK_IRQ +	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE  config SCHED_OMIT_FRAME_POINTER  	bool diff --git a/arch/s390/include/asm/bug.h b/arch/s390/include/asm/bug.h index 7efd0abe888..efb74fd5156 100644 --- a/arch/s390/include/asm/bug.h +++ b/arch/s390/include/asm/bug.h @@ -49,7 +49,7 @@  #define BUG() do {					\  	__EMIT_BUG(0);					\ -	for (;;);					\ +	unreachable();					\  } while (0)  #define WARN_ON(x) ({					\ diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h index 41ce6861174..c9af0d19c7a 100644 --- a/arch/s390/include/asm/spinlock.h +++ b/arch/s390/include/asm/spinlock.h @@ -191,33 +191,4 @@ static inline int __raw_write_trylock(raw_rwlock_t *rw)  #define _raw_read_relax(lock)	cpu_relax()  #define _raw_write_relax(lock)	cpu_relax() -#define __always_inline__spin_lock -#define __always_inline__read_lock -#define __always_inline__write_lock -#define __always_inline__spin_lock_bh -#define __always_inline__read_lock_bh -#define __always_inline__write_lock_bh -#define __always_inline__spin_lock_irq -#define __always_inline__read_lock_irq -#define __always_inline__write_lock_irq -#define __always_inline__spin_lock_irqsave -#define __always_inline__read_lock_irqsave -#define __always_inline__write_lock_irqsave -#define __always_inline__spin_trylock -#define __always_inline__read_trylock -#define __always_inline__write_trylock -#define __always_inline__spin_trylock_bh -#define __always_inline__spin_unlock -#define __always_inline__read_unlock -#define __always_inline__write_unlock -#define __always_inline__spin_unlock_bh -#define __always_inline__read_unlock_bh -#define __always_inline__write_unlock_bh -#define __always_inline__spin_unlock_irq -#define __always_inline__read_unlock_irq -#define __always_inline__write_unlock_irq -#define __always_inline__spin_unlock_irqrestore -#define __always_inline__read_unlock_irqrestore -#define __always_inline__write_unlock_irqrestore -  #endif /* __ASM_SPINLOCK_H */ diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index f5fe34dd821..5a82bc68193 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -203,73 +203,10 @@ out:  #ifdef CONFIG_FTRACE_SYSCALLS -extern unsigned long __start_syscalls_metadata[]; -extern unsigned long __stop_syscalls_metadata[];  extern unsigned int sys_call_table[]; -static struct syscall_metadata **syscalls_metadata; - -struct syscall_metadata *syscall_nr_to_meta(int nr) -{ -	if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) -		return NULL; - -	return syscalls_metadata[nr]; -} - -int syscall_name_to_nr(char *name) -{ -	int i; - -	if (!syscalls_metadata) -		return -1; -	for (i = 0; i < NR_syscalls; i++) -		if (syscalls_metadata[i]) -			if (!strcmp(syscalls_metadata[i]->name, name)) -				return i; -	return -1; -} - -void set_syscall_enter_id(int num, int id) -{ -	syscalls_metadata[num]->enter_id = id; -} - -void set_syscall_exit_id(int num, int id) +unsigned long __init arch_syscall_addr(int nr)  { -	syscalls_metadata[num]->exit_id = id; -} - -static struct syscall_metadata *find_syscall_meta(unsigned long syscall) -{ -	struct syscall_metadata *start; -	struct syscall_metadata *stop; -	char str[KSYM_SYMBOL_LEN]; - -	start = (struct syscall_metadata *)__start_syscalls_metadata; -	stop = (struct syscall_metadata *)__stop_syscalls_metadata; -	kallsyms_lookup(syscall, NULL, NULL, NULL, str); - -	for ( ; start < stop; start++) { -		if (start->name && !strcmp(start->name + 3, str + 3)) -			return start; -	} -	return NULL; -} - -static int __init arch_init_ftrace_syscalls(void) -{ -	struct syscall_metadata *meta; -	int i; -	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls, -				    GFP_KERNEL); -	if (!syscalls_metadata) -		return -ENOMEM; -	for (i = 0; i < NR_syscalls; i++) { -		meta = find_syscall_meta((unsigned long)sys_call_table[i]); -		syscalls_metadata[i] = meta; -	} -	return 0; +	return (unsigned long)sys_call_table[nr];  } -arch_initcall(arch_init_ftrace_syscalls);  #endif diff --git a/arch/x86/include/asm/amd_iommu.h b/arch/x86/include/asm/amd_iommu.h index 4b180897e6b..5af2982133b 100644 --- a/arch/x86/include/asm/amd_iommu.h +++ b/arch/x86/include/asm/amd_iommu.h @@ -1,5 +1,5 @@  /* - * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.   * Author: Joerg Roedel <joerg.roedel@amd.com>   *         Leo Duran <leo.duran@amd.com>   * @@ -23,19 +23,13 @@  #include <linux/irqreturn.h>  #ifdef CONFIG_AMD_IOMMU -extern int amd_iommu_init(void); -extern int amd_iommu_init_dma_ops(void); -extern int amd_iommu_init_passthrough(void); +  extern void amd_iommu_detect(void); -extern irqreturn_t amd_iommu_int_handler(int irq, void *data); -extern void amd_iommu_flush_all_domains(void); -extern void amd_iommu_flush_all_devices(void); -extern void amd_iommu_shutdown(void); -extern void amd_iommu_apply_erratum_63(u16 devid); +  #else -static inline int amd_iommu_init(void) { return -ENODEV; } +  static inline void amd_iommu_detect(void) { } -static inline void amd_iommu_shutdown(void) { } +  #endif  #endif /* _ASM_X86_AMD_IOMMU_H */ diff --git a/arch/x86/include/asm/amd_iommu_proto.h b/arch/x86/include/asm/amd_iommu_proto.h new file mode 100644 index 00000000000..84786fb9a23 --- /dev/null +++ b/arch/x86/include/asm/amd_iommu_proto.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2009 Advanced Micro Devices, Inc. + * Author: Joerg Roedel <joerg.roedel@amd.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA + */ + +#ifndef _ASM_X86_AMD_IOMMU_PROTO_H +#define _ASM_X86_AMD_IOMMU_PROTO_H + +struct amd_iommu; + +extern int amd_iommu_init_dma_ops(void); +extern int amd_iommu_init_passthrough(void); +extern irqreturn_t amd_iommu_int_handler(int irq, void *data); +extern void amd_iommu_flush_all_domains(void); +extern void amd_iommu_flush_all_devices(void); +extern void amd_iommu_apply_erratum_63(u16 devid); +extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu); + +#ifndef CONFIG_AMD_IOMMU_STATS + +static inline void amd_iommu_stats_init(void) { } + +#endif /* !CONFIG_AMD_IOMMU_STATS */ + +#endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */ diff --git a/arch/x86/include/asm/amd_iommu_types.h b/arch/x86/include/asm/amd_iommu_types.h index 2a2cc7a78a8..ba19ad4c47d 100644 --- a/arch/x86/include/asm/amd_iommu_types.h +++ b/arch/x86/include/asm/amd_iommu_types.h @@ -1,5 +1,5 @@  /* - * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.   * Author: Joerg Roedel <joerg.roedel@amd.com>   *         Leo Duran <leo.duran@amd.com>   * @@ -25,6 +25,11 @@  #include <linux/spinlock.h>  /* + * Maximum number of IOMMUs supported + */ +#define MAX_IOMMUS	32 + +/*   * some size calculation constants   */  #define DEV_TABLE_ENTRY_SIZE		32 @@ -206,6 +211,9 @@ extern bool amd_iommu_dump;  			printk(KERN_INFO "AMD-Vi: " format, ## arg);	\  	} while(0); +/* global flag if IOMMUs cache non-present entries */ +extern bool amd_iommu_np_cache; +  /*   * Make iterating over all IOMMUs easier   */ @@ -226,6 +234,8 @@ extern bool amd_iommu_dump;   * independent of their use.   */  struct protection_domain { +	struct list_head list;  /* for list of all protection domains */ +	struct list_head dev_list; /* List of all devices in this domain */  	spinlock_t lock;	/* mostly used to lock the page table*/  	u16 id;			/* the domain id written to the device table */  	int mode;		/* paging mode (0-6 levels) */ @@ -233,7 +243,20 @@ struct protection_domain {  	unsigned long flags;	/* flags to find out type of domain */  	bool updated;		/* complete domain flush required */  	unsigned dev_cnt;	/* devices assigned to this domain */ +	unsigned dev_iommu[MAX_IOMMUS]; /* per-IOMMU reference count */  	void *priv;		/* private data */ + +}; + +/* + * This struct contains device specific data for the IOMMU + */ +struct iommu_dev_data { +	struct list_head list;		  /* For domain->dev_list */ +	struct device *dev;		  /* Device this data belong to */ +	struct device *alias;		  /* The Alias Device */ +	struct protection_domain *domain; /* Domain the device is bound to */ +	atomic_t bind;			  /* Domain attach reverent count */  };  /* @@ -291,6 +314,9 @@ struct dma_ops_domain {  struct amd_iommu {  	struct list_head list; +	/* Index within the IOMMU array */ +	int index; +  	/* locks the accesses to the hardware */  	spinlock_t lock; @@ -357,6 +383,21 @@ struct amd_iommu {  extern struct list_head amd_iommu_list;  /* + * Array with pointers to each IOMMU struct + * The indices are referenced in the protection domains + */ +extern struct amd_iommu *amd_iommus[MAX_IOMMUS]; + +/* Number of IOMMUs present in the system */ +extern int amd_iommus_present; + +/* + * Declarations for the global list of all protection domains + */ +extern spinlock_t amd_iommu_pd_lock; +extern struct list_head amd_iommu_pd_list; + +/*   * Structure defining one entry in the device table   */  struct dev_table_entry { @@ -416,15 +457,9 @@ extern unsigned amd_iommu_aperture_order;  /* largest PCI device id we expect translation requests for */  extern u16 amd_iommu_last_bdf; -/* data structures for protection domain handling */ -extern struct protection_domain **amd_iommu_pd_table; -  /* allocation bitmap for domain ids */  extern unsigned long *amd_iommu_pd_alloc_bitmap; -/* will be 1 if device isolation is enabled */ -extern bool amd_iommu_isolate; -  /*   * If true, the addresses will be flushed on unmap time, not when   * they are reused @@ -462,11 +497,6 @@ struct __iommu_counter {  #define ADD_STATS_COUNTER(name, x)  #define SUB_STATS_COUNTER(name, x) -static inline void amd_iommu_stats_init(void) { } -  #endif /* CONFIG_AMD_IOMMU_STATS */ -/* some function prototypes */ -extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu); -  #endif /* _ASM_X86_AMD_IOMMU_TYPES_H */ diff --git a/arch/x86/include/asm/bug.h b/arch/x86/include/asm/bug.h index d9cf1cd156d..f654d1bb17f 100644 --- a/arch/x86/include/asm/bug.h +++ b/arch/x86/include/asm/bug.h @@ -22,14 +22,14 @@ do {								\  		     ".popsection"				\  		     : : "i" (__FILE__), "i" (__LINE__),	\  		     "i" (sizeof(struct bug_entry)));		\ -	for (;;) ;						\ +	unreachable();						\  } while (0)  #else  #define BUG()							\  do {								\  	asm volatile("ud2");					\ -	for (;;) ;						\ +	unreachable();						\  } while (0)  #endif diff --git a/arch/x86/include/asm/calgary.h b/arch/x86/include/asm/calgary.h index b03bedb62aa..0918654305a 100644 --- a/arch/x86/include/asm/calgary.h +++ b/arch/x86/include/asm/calgary.h @@ -62,10 +62,8 @@ struct cal_chipset_ops {  extern int use_calgary;  #ifdef CONFIG_CALGARY_IOMMU -extern int calgary_iommu_init(void);  extern void detect_calgary(void);  #else -static inline int calgary_iommu_init(void) { return 1; }  static inline void detect_calgary(void) { return; }  #endif diff --git a/arch/x86/include/asm/device.h b/arch/x86/include/asm/device.h index cee34e9ca45..029f230ab63 100644 --- a/arch/x86/include/asm/device.h +++ b/arch/x86/include/asm/device.h @@ -8,7 +8,7 @@ struct dev_archdata {  #ifdef CONFIG_X86_64  struct dma_map_ops *dma_ops;  #endif -#ifdef CONFIG_DMAR +#if defined(CONFIG_DMAR) || defined(CONFIG_AMD_IOMMU)  	void *iommu; /* hook for IOMMU specific extension */  #endif  }; diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h index 6a25d5d4283..0f6c02f3b7d 100644 --- a/arch/x86/include/asm/dma-mapping.h +++ b/arch/x86/include/asm/dma-mapping.h @@ -20,7 +20,8 @@  # define ISA_DMA_BIT_MASK DMA_BIT_MASK(32)  #endif -extern dma_addr_t bad_dma_address; +#define DMA_ERROR_CODE	0 +  extern int iommu_merge;  extern struct device x86_dma_fallback_dev;  extern int panic_on_overflow; @@ -48,7 +49,7 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)  	if (ops->mapping_error)  		return ops->mapping_error(dev, dma_addr); -	return (dma_addr == bad_dma_address); +	return (dma_addr == DMA_ERROR_CODE);  }  #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) diff --git a/arch/x86/include/asm/gart.h b/arch/x86/include/asm/gart.h index 6cfdafa409d..4ac5b0f33fc 100644 --- a/arch/x86/include/asm/gart.h +++ b/arch/x86/include/asm/gart.h @@ -35,8 +35,7 @@ extern int gart_iommu_aperture_allowed;  extern int gart_iommu_aperture_disabled;  extern void early_gart_iommu_check(void); -extern void gart_iommu_init(void); -extern void gart_iommu_shutdown(void); +extern int gart_iommu_init(void);  extern void __init gart_parse_options(char *);  extern void gart_iommu_hole_init(void); @@ -48,12 +47,6 @@ extern void gart_iommu_hole_init(void);  static inline void early_gart_iommu_check(void)  {  } -static inline void gart_iommu_init(void) -{ -} -static inline void gart_iommu_shutdown(void) -{ -}  static inline void gart_parse_options(char *options)  {  } diff --git a/arch/x86/include/asm/iommu.h b/arch/x86/include/asm/iommu.h index fd6d21bbee6..345c99cef15 100644 --- a/arch/x86/include/asm/iommu.h +++ b/arch/x86/include/asm/iommu.h @@ -1,8 +1,6 @@  #ifndef _ASM_X86_IOMMU_H  #define _ASM_X86_IOMMU_H -extern void pci_iommu_shutdown(void); -extern void no_iommu_init(void);  extern struct dma_map_ops nommu_dma_ops;  extern int force_iommu, no_iommu;  extern int iommu_detected; diff --git a/arch/x86/include/asm/swiotlb.h b/arch/x86/include/asm/swiotlb.h index b9e4e20174f..87ffcb12a1b 100644 --- a/arch/x86/include/asm/swiotlb.h +++ b/arch/x86/include/asm/swiotlb.h @@ -3,17 +3,14 @@  #include <linux/swiotlb.h> -/* SWIOTLB interface */ - -extern int swiotlb_force; -  #ifdef CONFIG_SWIOTLB  extern int swiotlb; -extern void pci_swiotlb_init(void); +extern int pci_swiotlb_init(void);  #else  #define swiotlb 0 -static inline void pci_swiotlb_init(void) +static inline int pci_swiotlb_init(void)  { +	return 0;  }  #endif diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 2c756fd4ab0..d8e71459f02 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -91,6 +91,14 @@ struct x86_init_timers {  };  /** + * struct x86_init_iommu - platform specific iommu setup + * @iommu_init:			platform specific iommu setup + */ +struct x86_init_iommu { +	int (*iommu_init)(void); +}; + +/**   * struct x86_init_ops - functions for platform specific setup   *   */ @@ -101,6 +109,7 @@ struct x86_init_ops {  	struct x86_init_oem		oem;  	struct x86_init_paging		paging;  	struct x86_init_timers		timers; +	struct x86_init_iommu		iommu;  };  /** @@ -121,6 +130,7 @@ struct x86_platform_ops {  	unsigned long (*calibrate_tsc)(void);  	unsigned long (*get_wallclock)(void);  	int (*set_wallclock)(unsigned long nowtime); +	void (*iommu_shutdown)(void);  };  extern struct x86_init_ops x86_init; diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index 0285521e0a9..32fb09102a1 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c @@ -1,5 +1,5 @@  /* - * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.   * Author: Joerg Roedel <joerg.roedel@amd.com>   *         Leo Duran <leo.duran@amd.com>   * @@ -28,6 +28,7 @@  #include <asm/proto.h>  #include <asm/iommu.h>  #include <asm/gart.h> +#include <asm/amd_iommu_proto.h>  #include <asm/amd_iommu_types.h>  #include <asm/amd_iommu.h> @@ -56,20 +57,115 @@ struct iommu_cmd {  	u32 data[4];  }; -static int dma_ops_unity_map(struct dma_ops_domain *dma_dom, -			     struct unity_map_entry *e); -static struct dma_ops_domain *find_protection_domain(u16 devid); -static u64 *alloc_pte(struct protection_domain *domain, -		      unsigned long address, int end_lvl, -		      u64 **pte_page, gfp_t gfp); -static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, -				      unsigned long start_page, -				      unsigned int pages);  static void reset_iommu_command_buffer(struct amd_iommu *iommu); -static u64 *fetch_pte(struct protection_domain *domain, -		      unsigned long address, int map_size);  static void update_domain(struct protection_domain *domain); +/**************************************************************************** + * + * Helper functions + * + ****************************************************************************/ + +static inline u16 get_device_id(struct device *dev) +{ +	struct pci_dev *pdev = to_pci_dev(dev); + +	return calc_devid(pdev->bus->number, pdev->devfn); +} + +static struct iommu_dev_data *get_dev_data(struct device *dev) +{ +	return dev->archdata.iommu; +} + +/* + * In this function the list of preallocated protection domains is traversed to + * find the domain for a specific device + */ +static struct dma_ops_domain *find_protection_domain(u16 devid) +{ +	struct dma_ops_domain *entry, *ret = NULL; +	unsigned long flags; +	u16 alias = amd_iommu_alias_table[devid]; + +	if (list_empty(&iommu_pd_list)) +		return NULL; + +	spin_lock_irqsave(&iommu_pd_list_lock, flags); + +	list_for_each_entry(entry, &iommu_pd_list, list) { +		if (entry->target_dev == devid || +		    entry->target_dev == alias) { +			ret = entry; +			break; +		} +	} + +	spin_unlock_irqrestore(&iommu_pd_list_lock, flags); + +	return ret; +} + +/* + * This function checks if the driver got a valid device from the caller to + * avoid dereferencing invalid pointers. + */ +static bool check_device(struct device *dev) +{ +	u16 devid; + +	if (!dev || !dev->dma_mask) +		return false; + +	/* No device or no PCI device */ +	if (!dev || dev->bus != &pci_bus_type) +		return false; + +	devid = get_device_id(dev); + +	/* Out of our scope? */ +	if (devid > amd_iommu_last_bdf) +		return false; + +	if (amd_iommu_rlookup_table[devid] == NULL) +		return false; + +	return true; +} + +static int iommu_init_device(struct device *dev) +{ +	struct iommu_dev_data *dev_data; +	struct pci_dev *pdev; +	u16 devid, alias; + +	if (dev->archdata.iommu) +		return 0; + +	dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL); +	if (!dev_data) +		return -ENOMEM; + +	dev_data->dev = dev; + +	devid = get_device_id(dev); +	alias = amd_iommu_alias_table[devid]; +	pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff); +	if (pdev) +		dev_data->alias = &pdev->dev; + +	atomic_set(&dev_data->bind, 0); + +	dev->archdata.iommu = dev_data; + + +	return 0; +} + +static void iommu_uninit_device(struct device *dev) +{ +	kfree(dev->archdata.iommu); +}  #ifdef CONFIG_AMD_IOMMU_STATS  /* @@ -90,7 +186,6 @@ DECLARE_STATS_COUNTER(alloced_io_mem);  DECLARE_STATS_COUNTER(total_map_requests);  static struct dentry *stats_dir; -static struct dentry *de_isolate;  static struct dentry *de_fflush;  static void amd_iommu_stats_add(struct __iommu_counter *cnt) @@ -108,9 +203,6 @@ static void amd_iommu_stats_init(void)  	if (stats_dir == NULL)  		return; -	de_isolate = debugfs_create_bool("isolation", 0444, stats_dir, -					 (u32 *)&amd_iommu_isolate); -  	de_fflush  = debugfs_create_bool("fullflush", 0444, stats_dir,  					 (u32 *)&amd_iommu_unmap_flush); @@ -130,12 +222,6 @@ static void amd_iommu_stats_init(void)  #endif -/* returns !0 if the IOMMU is caching non-present entries in its TLB */ -static int iommu_has_npcache(struct amd_iommu *iommu) -{ -	return iommu->cap & (1UL << IOMMU_CAP_NPCACHE); -} -  /****************************************************************************   *   * Interrupt handling functions @@ -199,6 +285,7 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt)  		break;  	case EVENT_TYPE_ILL_CMD:  		printk("ILLEGAL_COMMAND_ERROR address=0x%016llx]\n", address); +		iommu->reset_in_progress = true;  		reset_iommu_command_buffer(iommu);  		dump_command(address);  		break; @@ -321,11 +408,8 @@ static void __iommu_wait_for_completion(struct amd_iommu *iommu)  	status &= ~MMIO_STATUS_COM_WAIT_INT_MASK;  	writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); -	if (unlikely(i == EXIT_LOOP_COUNT)) { -		spin_unlock(&iommu->lock); -		reset_iommu_command_buffer(iommu); -		spin_lock(&iommu->lock); -	} +	if (unlikely(i == EXIT_LOOP_COUNT)) +		iommu->reset_in_progress = true;  }  /* @@ -372,26 +456,46 @@ static int iommu_completion_wait(struct amd_iommu *iommu)  out:  	spin_unlock_irqrestore(&iommu->lock, flags); +	if (iommu->reset_in_progress) +		reset_iommu_command_buffer(iommu); +  	return 0;  } +static void iommu_flush_complete(struct protection_domain *domain) +{ +	int i; + +	for (i = 0; i < amd_iommus_present; ++i) { +		if (!domain->dev_iommu[i]) +			continue; + +		/* +		 * Devices of this domain are behind this IOMMU +		 * We need to wait for completion of all commands. +		 */ +		iommu_completion_wait(amd_iommus[i]); +	} +} +  /*   * Command send function for invalidating a device table entry   */ -static int iommu_queue_inv_dev_entry(struct amd_iommu *iommu, u16 devid) +static int iommu_flush_device(struct device *dev)  { +	struct amd_iommu *iommu;  	struct iommu_cmd cmd; -	int ret; +	u16 devid; -	BUG_ON(iommu == NULL); +	devid = get_device_id(dev); +	iommu = amd_iommu_rlookup_table[devid]; +	/* Build command */  	memset(&cmd, 0, sizeof(cmd));  	CMD_SET_TYPE(&cmd, CMD_INV_DEV_ENTRY);  	cmd.data[0] = devid; -	ret = iommu_queue_command(iommu, &cmd); - -	return ret; +	return iommu_queue_command(iommu, &cmd);  }  static void __iommu_build_inv_iommu_pages(struct iommu_cmd *cmd, u64 address, @@ -430,11 +534,11 @@ static int iommu_queue_inv_iommu_pages(struct amd_iommu *iommu,   * It invalidates a single PTE if the range to flush is within a single   * page. Otherwise it flushes the whole TLB of the IOMMU.   */ -static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid, -		u64 address, size_t size) +static void __iommu_flush_pages(struct protection_domain *domain, +				u64 address, size_t size, int pde)  { -	int s = 0; -	unsigned pages = iommu_num_pages(address, size, PAGE_SIZE); +	int s = 0, i; +	unsigned long pages = iommu_num_pages(address, size, PAGE_SIZE);  	address &= PAGE_MASK; @@ -447,142 +551,212 @@ static int iommu_flush_pages(struct amd_iommu *iommu, u16 domid,  		s = 1;  	} -	iommu_queue_inv_iommu_pages(iommu, address, domid, 0, s); -	return 0; +	for (i = 0; i < amd_iommus_present; ++i) { +		if (!domain->dev_iommu[i]) +			continue; + +		/* +		 * Devices of this domain are behind this IOMMU +		 * We need a TLB flush +		 */ +		iommu_queue_inv_iommu_pages(amd_iommus[i], address, +					    domain->id, pde, s); +	} + +	return;  } -/* Flush the whole IO/TLB for a given protection domain */ -static void iommu_flush_tlb(struct amd_iommu *iommu, u16 domid) +static void iommu_flush_pages(struct protection_domain *domain, +			     u64 address, size_t size)  { -	u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; - -	INC_STATS_COUNTER(domain_flush_single); +	__iommu_flush_pages(domain, address, size, 0); +} -	iommu_queue_inv_iommu_pages(iommu, address, domid, 0, 1); +/* Flush the whole IO/TLB for a given protection domain */ +static void iommu_flush_tlb(struct protection_domain *domain) +{ +	__iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 0);  }  /* Flush the whole IO/TLB for a given protection domain - including PDE */ -static void iommu_flush_tlb_pde(struct amd_iommu *iommu, u16 domid) +static void iommu_flush_tlb_pde(struct protection_domain *domain)  { -       u64 address = CMD_INV_IOMMU_ALL_PAGES_ADDRESS; - -       INC_STATS_COUNTER(domain_flush_single); - -       iommu_queue_inv_iommu_pages(iommu, address, domid, 1, 1); +	__iommu_flush_pages(domain, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, 1);  } +  /* - * This function flushes one domain on one IOMMU + * This function flushes the DTEs for all devices in domain   */ -static void flush_domain_on_iommu(struct amd_iommu *iommu, u16 domid) +static void iommu_flush_domain_devices(struct protection_domain *domain)  { -	struct iommu_cmd cmd; +	struct iommu_dev_data *dev_data;  	unsigned long flags; -	__iommu_build_inv_iommu_pages(&cmd, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, -				      domid, 1, 1); +	spin_lock_irqsave(&domain->lock, flags); -	spin_lock_irqsave(&iommu->lock, flags); -	__iommu_queue_command(iommu, &cmd); -	__iommu_completion_wait(iommu); -	__iommu_wait_for_completion(iommu); -	spin_unlock_irqrestore(&iommu->lock, flags); +	list_for_each_entry(dev_data, &domain->dev_list, list) +		iommu_flush_device(dev_data->dev); + +	spin_unlock_irqrestore(&domain->lock, flags);  } -static void flush_all_domains_on_iommu(struct amd_iommu *iommu) +static void iommu_flush_all_domain_devices(void)  { -	int i; +	struct protection_domain *domain; +	unsigned long flags; -	for (i = 1; i < MAX_DOMAIN_ID; ++i) { -		if (!test_bit(i, amd_iommu_pd_alloc_bitmap)) -			continue; -		flush_domain_on_iommu(iommu, i); +	spin_lock_irqsave(&amd_iommu_pd_lock, flags); + +	list_for_each_entry(domain, &amd_iommu_pd_list, list) { +		iommu_flush_domain_devices(domain); +		iommu_flush_complete(domain);  	} +	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); +} + +void amd_iommu_flush_all_devices(void) +{ +	iommu_flush_all_domain_devices();  }  /* - * This function is used to flush the IO/TLB for a given protection domain - * on every IOMMU in the system + * This function uses heavy locking and may disable irqs for some time. But + * this is no issue because it is only called during resume.   */ -static void iommu_flush_domain(u16 domid) +void amd_iommu_flush_all_domains(void)  { -	struct amd_iommu *iommu; +	struct protection_domain *domain; +	unsigned long flags; -	INC_STATS_COUNTER(domain_flush_all); +	spin_lock_irqsave(&amd_iommu_pd_lock, flags); -	for_each_iommu(iommu) -		flush_domain_on_iommu(iommu, domid); +	list_for_each_entry(domain, &amd_iommu_pd_list, list) { +		spin_lock(&domain->lock); +		iommu_flush_tlb_pde(domain); +		iommu_flush_complete(domain); +		spin_unlock(&domain->lock); +	} + +	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags);  } -void amd_iommu_flush_all_domains(void) +static void reset_iommu_command_buffer(struct amd_iommu *iommu)  { -	struct amd_iommu *iommu; +	pr_err("AMD-Vi: Resetting IOMMU command buffer\n"); -	for_each_iommu(iommu) -		flush_all_domains_on_iommu(iommu); +	if (iommu->reset_in_progress) +		panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n"); + +	amd_iommu_reset_cmd_buffer(iommu); +	amd_iommu_flush_all_devices(); +	amd_iommu_flush_all_domains(); + +	iommu->reset_in_progress = false;  } -static void flush_all_devices_for_iommu(struct amd_iommu *iommu) +/**************************************************************************** + * + * The functions below are used the create the page table mappings for + * unity mapped regions. + * + ****************************************************************************/ + +/* + * This function is used to add another level to an IO page table. Adding + * another level increases the size of the address space by 9 bits to a size up + * to 64 bits. + */ +static bool increase_address_space(struct protection_domain *domain, +				   gfp_t gfp)  { -	int i; +	u64 *pte; -	for (i = 0; i <= amd_iommu_last_bdf; ++i) { -		if (iommu != amd_iommu_rlookup_table[i]) -			continue; +	if (domain->mode == PAGE_MODE_6_LEVEL) +		/* address space already 64 bit large */ +		return false; -		iommu_queue_inv_dev_entry(iommu, i); -		iommu_completion_wait(iommu); -	} +	pte = (void *)get_zeroed_page(gfp); +	if (!pte) +		return false; + +	*pte             = PM_LEVEL_PDE(domain->mode, +					virt_to_phys(domain->pt_root)); +	domain->pt_root  = pte; +	domain->mode    += 1; +	domain->updated  = true; + +	return true;  } -static void flush_devices_by_domain(struct protection_domain *domain) +static u64 *alloc_pte(struct protection_domain *domain, +		      unsigned long address, +		      int end_lvl, +		      u64 **pte_page, +		      gfp_t gfp)  { -	struct amd_iommu *iommu; -	int i; +	u64 *pte, *page; +	int level; -	for (i = 0; i <= amd_iommu_last_bdf; ++i) { -		if ((domain == NULL && amd_iommu_pd_table[i] == NULL) || -		    (amd_iommu_pd_table[i] != domain)) -			continue; +	while (address > PM_LEVEL_SIZE(domain->mode)) +		increase_address_space(domain, gfp); -		iommu = amd_iommu_rlookup_table[i]; -		if (!iommu) -			continue; +	level =  domain->mode - 1; +	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; -		iommu_queue_inv_dev_entry(iommu, i); -		iommu_completion_wait(iommu); +	while (level > end_lvl) { +		if (!IOMMU_PTE_PRESENT(*pte)) { +			page = (u64 *)get_zeroed_page(gfp); +			if (!page) +				return NULL; +			*pte = PM_LEVEL_PDE(level, virt_to_phys(page)); +		} + +		level -= 1; + +		pte = IOMMU_PTE_PAGE(*pte); + +		if (pte_page && level == end_lvl) +			*pte_page = pte; + +		pte = &pte[PM_LEVEL_INDEX(level, address)];  	} + +	return pte;  } -static void reset_iommu_command_buffer(struct amd_iommu *iommu) +/* + * This function checks if there is a PTE for a given dma address. If + * there is one, it returns the pointer to it. + */ +static u64 *fetch_pte(struct protection_domain *domain, +		      unsigned long address, int map_size)  { -	pr_err("AMD-Vi: Resetting IOMMU command buffer\n"); +	int level; +	u64 *pte; -	if (iommu->reset_in_progress) -		panic("AMD-Vi: ILLEGAL_COMMAND_ERROR while resetting command buffer\n"); +	level =  domain->mode - 1; +	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; -	iommu->reset_in_progress = true; +	while (level > map_size) { +		if (!IOMMU_PTE_PRESENT(*pte)) +			return NULL; -	amd_iommu_reset_cmd_buffer(iommu); -	flush_all_devices_for_iommu(iommu); -	flush_all_domains_on_iommu(iommu); +		level -= 1; -	iommu->reset_in_progress = false; -} +		pte = IOMMU_PTE_PAGE(*pte); +		pte = &pte[PM_LEVEL_INDEX(level, address)]; -void amd_iommu_flush_all_devices(void) -{ -	flush_devices_by_domain(NULL); -} +		if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) { +			pte = NULL; +			break; +		} +	} -/**************************************************************************** - * - * The functions below are used the create the page table mappings for - * unity mapped regions. - * - ****************************************************************************/ +	return pte; +}  /*   * Generic mapping functions. It maps a physical address into a DMA @@ -654,28 +828,6 @@ static int iommu_for_unity_map(struct amd_iommu *iommu,  }  /* - * Init the unity mappings for a specific IOMMU in the system - * - * Basically iterates over all unity mapping entries and applies them to - * the default domain DMA of that IOMMU if necessary. - */ -static int iommu_init_unity_mappings(struct amd_iommu *iommu) -{ -	struct unity_map_entry *entry; -	int ret; - -	list_for_each_entry(entry, &amd_iommu_unity_map, list) { -		if (!iommu_for_unity_map(iommu, entry)) -			continue; -		ret = dma_ops_unity_map(iommu->default_dom, entry); -		if (ret) -			return ret; -	} - -	return 0; -} - -/*   * This function actually applies the mapping to the page table of the   * dma_ops domain.   */ @@ -704,6 +856,28 @@ static int dma_ops_unity_map(struct dma_ops_domain *dma_dom,  }  /* + * Init the unity mappings for a specific IOMMU in the system + * + * Basically iterates over all unity mapping entries and applies them to + * the default domain DMA of that IOMMU if necessary. + */ +static int iommu_init_unity_mappings(struct amd_iommu *iommu) +{ +	struct unity_map_entry *entry; +	int ret; + +	list_for_each_entry(entry, &amd_iommu_unity_map, list) { +		if (!iommu_for_unity_map(iommu, entry)) +			continue; +		ret = dma_ops_unity_map(iommu->default_dom, entry); +		if (ret) +			return ret; +	} + +	return 0; +} + +/*   * Inits the unity mappings required for a specific device   */  static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom, @@ -740,34 +914,23 @@ static int init_unity_mappings_for_device(struct dma_ops_domain *dma_dom,   */  /* - * This function checks if there is a PTE for a given dma address. If - * there is one, it returns the pointer to it. + * Used to reserve address ranges in the aperture (e.g. for exclusion + * ranges.   */ -static u64 *fetch_pte(struct protection_domain *domain, -		      unsigned long address, int map_size) +static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, +				      unsigned long start_page, +				      unsigned int pages)  { -	int level; -	u64 *pte; - -	level =  domain->mode - 1; -	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; - -	while (level > map_size) { -		if (!IOMMU_PTE_PRESENT(*pte)) -			return NULL; - -		level -= 1; +	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT; -		pte = IOMMU_PTE_PAGE(*pte); -		pte = &pte[PM_LEVEL_INDEX(level, address)]; +	if (start_page + pages > last_page) +		pages = last_page - start_page; -		if ((PM_PTE_LEVEL(*pte) == 0) && level != map_size) { -			pte = NULL; -			break; -		} +	for (i = start_page; i < start_page + pages; ++i) { +		int index = i / APERTURE_RANGE_PAGES; +		int page  = i % APERTURE_RANGE_PAGES; +		__set_bit(page, dom->aperture[index]->bitmap);  	} - -	return pte;  }  /* @@ -775,11 +938,11 @@ static u64 *fetch_pte(struct protection_domain *domain,   * aperture in case of dma_ops domain allocation or address allocation   * failure.   */ -static int alloc_new_range(struct amd_iommu *iommu, -			   struct dma_ops_domain *dma_dom, +static int alloc_new_range(struct dma_ops_domain *dma_dom,  			   bool populate, gfp_t gfp)  {  	int index = dma_dom->aperture_size >> APERTURE_RANGE_SHIFT; +	struct amd_iommu *iommu;  	int i;  #ifdef CONFIG_IOMMU_STRESS @@ -819,14 +982,17 @@ static int alloc_new_range(struct amd_iommu *iommu,  	dma_dom->aperture_size += APERTURE_RANGE_SIZE;  	/* Intialize the exclusion range if necessary */ -	if (iommu->exclusion_start && -	    iommu->exclusion_start >= dma_dom->aperture[index]->offset && -	    iommu->exclusion_start < dma_dom->aperture_size) { -		unsigned long startpage = iommu->exclusion_start >> PAGE_SHIFT; -		int pages = iommu_num_pages(iommu->exclusion_start, -					    iommu->exclusion_length, -					    PAGE_SIZE); -		dma_ops_reserve_addresses(dma_dom, startpage, pages); +	for_each_iommu(iommu) { +		if (iommu->exclusion_start && +		    iommu->exclusion_start >= dma_dom->aperture[index]->offset +		    && iommu->exclusion_start < dma_dom->aperture_size) { +			unsigned long startpage; +			int pages = iommu_num_pages(iommu->exclusion_start, +						    iommu->exclusion_length, +						    PAGE_SIZE); +			startpage = iommu->exclusion_start >> PAGE_SHIFT; +			dma_ops_reserve_addresses(dma_dom, startpage, pages); +		}  	}  	/* @@ -928,7 +1094,7 @@ static unsigned long dma_ops_alloc_addresses(struct device *dev,  	}  	if (unlikely(address == -1)) -		address = bad_dma_address; +		address = DMA_ERROR_CODE;  	WARN_ON((address + (PAGE_SIZE*pages)) > dom->aperture_size); @@ -973,6 +1139,31 @@ static void dma_ops_free_addresses(struct dma_ops_domain *dom,   *   ****************************************************************************/ +/* + * This function adds a protection domain to the global protection domain list + */ +static void add_domain_to_list(struct protection_domain *domain) +{ +	unsigned long flags; + +	spin_lock_irqsave(&amd_iommu_pd_lock, flags); +	list_add(&domain->list, &amd_iommu_pd_list); +	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); +} + +/* + * This function removes a protection domain to the global + * protection domain list + */ +static void del_domain_from_list(struct protection_domain *domain) +{ +	unsigned long flags; + +	spin_lock_irqsave(&amd_iommu_pd_lock, flags); +	list_del(&domain->list); +	spin_unlock_irqrestore(&amd_iommu_pd_lock, flags); +} +  static u16 domain_id_alloc(void)  {  	unsigned long flags; @@ -1000,26 +1191,6 @@ static void domain_id_free(int id)  	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);  } -/* - * Used to reserve address ranges in the aperture (e.g. for exclusion - * ranges. - */ -static void dma_ops_reserve_addresses(struct dma_ops_domain *dom, -				      unsigned long start_page, -				      unsigned int pages) -{ -	unsigned int i, last_page = dom->aperture_size >> PAGE_SHIFT; - -	if (start_page + pages > last_page) -		pages = last_page - start_page; - -	for (i = start_page; i < start_page + pages; ++i) { -		int index = i / APERTURE_RANGE_PAGES; -		int page  = i % APERTURE_RANGE_PAGES; -		__set_bit(page, dom->aperture[index]->bitmap); -	} -} -  static void free_pagetable(struct protection_domain *domain)  {  	int i, j; @@ -1061,6 +1232,8 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)  	if (!dom)  		return; +	del_domain_from_list(&dom->domain); +  	free_pagetable(&dom->domain);  	for (i = 0; i < APERTURE_MAX_RANGES; ++i) { @@ -1078,7 +1251,7 @@ static void dma_ops_domain_free(struct dma_ops_domain *dom)   * It also intializes the page table and the address allocator data   * structures required for the dma_ops interface   */ -static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu) +static struct dma_ops_domain *dma_ops_domain_alloc(void)  {  	struct dma_ops_domain *dma_dom; @@ -1091,6 +1264,7 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)  	dma_dom->domain.id = domain_id_alloc();  	if (dma_dom->domain.id == 0)  		goto free_dma_dom; +	INIT_LIST_HEAD(&dma_dom->domain.dev_list);  	dma_dom->domain.mode = PAGE_MODE_2_LEVEL;  	dma_dom->domain.pt_root = (void *)get_zeroed_page(GFP_KERNEL);  	dma_dom->domain.flags = PD_DMA_OPS_MASK; @@ -1101,7 +1275,9 @@ static struct dma_ops_domain *dma_ops_domain_alloc(struct amd_iommu *iommu)  	dma_dom->need_flush = false;  	dma_dom->target_dev = 0xffff; -	if (alloc_new_range(iommu, dma_dom, true, GFP_KERNEL)) +	add_domain_to_list(&dma_dom->domain); + +	if (alloc_new_range(dma_dom, true, GFP_KERNEL))  		goto free_dma_dom;  	/* @@ -1129,22 +1305,6 @@ static bool dma_ops_domain(struct protection_domain *domain)  	return domain->flags & PD_DMA_OPS_MASK;  } -/* - * Find out the protection domain structure for a given PCI device. This - * will give us the pointer to the page table root for example. - */ -static struct protection_domain *domain_for_device(u16 devid) -{ -	struct protection_domain *dom; -	unsigned long flags; - -	read_lock_irqsave(&amd_iommu_devtable_lock, flags); -	dom = amd_iommu_pd_table[devid]; -	read_unlock_irqrestore(&amd_iommu_devtable_lock, flags); - -	return dom; -} -  static void set_dte_entry(u16 devid, struct protection_domain *domain)  {  	u64 pte_root = virt_to_phys(domain->pt_root); @@ -1156,42 +1316,123 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain)  	amd_iommu_dev_table[devid].data[2] = domain->id;  	amd_iommu_dev_table[devid].data[1] = upper_32_bits(pte_root);  	amd_iommu_dev_table[devid].data[0] = lower_32_bits(pte_root); +} + +static void clear_dte_entry(u16 devid) +{ +	/* remove entry from the device table seen by the hardware */ +	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; +	amd_iommu_dev_table[devid].data[1] = 0; +	amd_iommu_dev_table[devid].data[2] = 0; -	amd_iommu_pd_table[devid] = domain; +	amd_iommu_apply_erratum_63(devid); +} + +static void do_attach(struct device *dev, struct protection_domain *domain) +{ +	struct iommu_dev_data *dev_data; +	struct amd_iommu *iommu; +	u16 devid; + +	devid    = get_device_id(dev); +	iommu    = amd_iommu_rlookup_table[devid]; +	dev_data = get_dev_data(dev); + +	/* Update data structures */ +	dev_data->domain = domain; +	list_add(&dev_data->list, &domain->dev_list); +	set_dte_entry(devid, domain); + +	/* Do reference counting */ +	domain->dev_iommu[iommu->index] += 1; +	domain->dev_cnt                 += 1; + +	/* Flush the DTE entry */ +	iommu_flush_device(dev); +} + +static void do_detach(struct device *dev) +{ +	struct iommu_dev_data *dev_data; +	struct amd_iommu *iommu; +	u16 devid; + +	devid    = get_device_id(dev); +	iommu    = amd_iommu_rlookup_table[devid]; +	dev_data = get_dev_data(dev); + +	/* decrease reference counters */ +	dev_data->domain->dev_iommu[iommu->index] -= 1; +	dev_data->domain->dev_cnt                 -= 1; + +	/* Update data structures */ +	dev_data->domain = NULL; +	list_del(&dev_data->list); +	clear_dte_entry(devid); + +	/* Flush the DTE entry */ +	iommu_flush_device(dev);  }  /*   * If a device is not yet associated with a domain, this function does   * assigns it visible for the hardware   */ -static void __attach_device(struct amd_iommu *iommu, -			    struct protection_domain *domain, -			    u16 devid) +static int __attach_device(struct device *dev, +			   struct protection_domain *domain)  { +	struct iommu_dev_data *dev_data, *alias_data; + +	dev_data   = get_dev_data(dev); +	alias_data = get_dev_data(dev_data->alias); + +	if (!alias_data) +		return -EINVAL; +  	/* lock domain */  	spin_lock(&domain->lock); -	/* update DTE entry */ -	set_dte_entry(devid, domain); +	/* Some sanity checks */ +	if (alias_data->domain != NULL && +	    alias_data->domain != domain) +		return -EBUSY; -	domain->dev_cnt += 1; +	if (dev_data->domain != NULL && +	    dev_data->domain != domain) +		return -EBUSY; + +	/* Do real assignment */ +	if (dev_data->alias != dev) { +		alias_data = get_dev_data(dev_data->alias); +		if (alias_data->domain == NULL) +			do_attach(dev_data->alias, domain); + +		atomic_inc(&alias_data->bind); +	} + +	if (dev_data->domain == NULL) +		do_attach(dev, domain); + +	atomic_inc(&dev_data->bind);  	/* ready */  	spin_unlock(&domain->lock); + +	return 0;  }  /*   * If a device is not yet associated with a domain, this function does   * assigns it visible for the hardware   */ -static void attach_device(struct amd_iommu *iommu, -			  struct protection_domain *domain, -			  u16 devid) +static int attach_device(struct device *dev, +			 struct protection_domain *domain)  {  	unsigned long flags; +	int ret;  	write_lock_irqsave(&amd_iommu_devtable_lock, flags); -	__attach_device(iommu, domain, devid); +	ret = __attach_device(dev, domain);  	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);  	/* @@ -1199,98 +1440,125 @@ static void attach_device(struct amd_iommu *iommu,  	 * left the caches in the IOMMU dirty. So we have to flush  	 * here to evict all dirty stuff.  	 */ -	iommu_queue_inv_dev_entry(iommu, devid); -	iommu_flush_tlb_pde(iommu, domain->id); +	iommu_flush_tlb_pde(domain); + +	return ret;  }  /*   * Removes a device from a protection domain (unlocked)   */ -static void __detach_device(struct protection_domain *domain, u16 devid) +static void __detach_device(struct device *dev)  { +	struct iommu_dev_data *dev_data = get_dev_data(dev); +	struct iommu_dev_data *alias_data; +	unsigned long flags; -	/* lock domain */ -	spin_lock(&domain->lock); - -	/* remove domain from the lookup table */ -	amd_iommu_pd_table[devid] = NULL; +	BUG_ON(!dev_data->domain); -	/* remove entry from the device table seen by the hardware */ -	amd_iommu_dev_table[devid].data[0] = IOMMU_PTE_P | IOMMU_PTE_TV; -	amd_iommu_dev_table[devid].data[1] = 0; -	amd_iommu_dev_table[devid].data[2] = 0; +	spin_lock_irqsave(&dev_data->domain->lock, flags); -	amd_iommu_apply_erratum_63(devid); +	if (dev_data->alias != dev) { +		alias_data = get_dev_data(dev_data->alias); +		if (atomic_dec_and_test(&alias_data->bind)) +			do_detach(dev_data->alias); +	} -	/* decrease reference counter */ -	domain->dev_cnt -= 1; +	if (atomic_dec_and_test(&dev_data->bind)) +		do_detach(dev); -	/* ready */ -	spin_unlock(&domain->lock); +	spin_unlock_irqrestore(&dev_data->domain->lock, flags);  	/*  	 * If we run in passthrough mode the device must be assigned to the  	 * passthrough domain if it is detached from any other domain  	 */ -	if (iommu_pass_through) { -		struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; -		__attach_device(iommu, pt_domain, devid); -	} +	if (iommu_pass_through && dev_data->domain == NULL) +		__attach_device(dev, pt_domain);  }  /*   * Removes a device from a protection domain (with devtable_lock held)   */ -static void detach_device(struct protection_domain *domain, u16 devid) +static void detach_device(struct device *dev)  {  	unsigned long flags;  	/* lock device table */  	write_lock_irqsave(&amd_iommu_devtable_lock, flags); -	__detach_device(domain, devid); +	__detach_device(dev);  	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);  } +/* + * Find out the protection domain structure for a given PCI device. This + * will give us the pointer to the page table root for example. + */ +static struct protection_domain *domain_for_device(struct device *dev) +{ +	struct protection_domain *dom; +	struct iommu_dev_data *dev_data, *alias_data; +	unsigned long flags; +	u16 devid, alias; + +	devid      = get_device_id(dev); +	alias      = amd_iommu_alias_table[devid]; +	dev_data   = get_dev_data(dev); +	alias_data = get_dev_data(dev_data->alias); +	if (!alias_data) +		return NULL; + +	read_lock_irqsave(&amd_iommu_devtable_lock, flags); +	dom = dev_data->domain; +	if (dom == NULL && +	    alias_data->domain != NULL) { +		__attach_device(dev, alias_data->domain); +		dom = alias_data->domain; +	} + +	read_unlock_irqrestore(&amd_iommu_devtable_lock, flags); + +	return dom; +} +  static int device_change_notifier(struct notifier_block *nb,  				  unsigned long action, void *data)  {  	struct device *dev = data; -	struct pci_dev *pdev = to_pci_dev(dev); -	u16 devid = calc_devid(pdev->bus->number, pdev->devfn); +	u16 devid;  	struct protection_domain *domain;  	struct dma_ops_domain *dma_domain;  	struct amd_iommu *iommu;  	unsigned long flags; -	if (devid > amd_iommu_last_bdf) -		goto out; - -	devid = amd_iommu_alias_table[devid]; - -	iommu = amd_iommu_rlookup_table[devid]; -	if (iommu == NULL) -		goto out; - -	domain = domain_for_device(devid); +	if (!check_device(dev)) +		return 0; -	if (domain && !dma_ops_domain(domain)) -		WARN_ONCE(1, "AMD IOMMU WARNING: device %s already bound " -			  "to a non-dma-ops domain\n", dev_name(dev)); +	devid  = get_device_id(dev); +	iommu  = amd_iommu_rlookup_table[devid];  	switch (action) {  	case BUS_NOTIFY_UNBOUND_DRIVER: + +		domain = domain_for_device(dev); +  		if (!domain)  			goto out;  		if (iommu_pass_through)  			break; -		detach_device(domain, devid); +		detach_device(dev);  		break;  	case BUS_NOTIFY_ADD_DEVICE: + +		iommu_init_device(dev); + +		domain = domain_for_device(dev); +  		/* allocate a protection domain if a device is added */  		dma_domain = find_protection_domain(devid);  		if (dma_domain)  			goto out; -		dma_domain = dma_ops_domain_alloc(iommu); +		dma_domain = dma_ops_domain_alloc();  		if (!dma_domain)  			goto out;  		dma_domain->target_dev = devid; @@ -1300,11 +1568,15 @@ static int device_change_notifier(struct notifier_block *nb,  		spin_unlock_irqrestore(&iommu_pd_list_lock, flags);  		break; +	case BUS_NOTIFY_DEL_DEVICE: + +		iommu_uninit_device(dev); +  	default:  		goto out;  	} -	iommu_queue_inv_dev_entry(iommu, devid); +	iommu_flush_device(dev);  	iommu_completion_wait(iommu);  out: @@ -1322,106 +1594,46 @@ static struct notifier_block device_nb = {   *****************************************************************************/  /* - * This function checks if the driver got a valid device from the caller to - * avoid dereferencing invalid pointers. - */ -static bool check_device(struct device *dev) -{ -	if (!dev || !dev->dma_mask) -		return false; - -	return true; -} - -/* - * In this function the list of preallocated protection domains is traversed to - * find the domain for a specific device - */ -static struct dma_ops_domain *find_protection_domain(u16 devid) -{ -	struct dma_ops_domain *entry, *ret = NULL; -	unsigned long flags; - -	if (list_empty(&iommu_pd_list)) -		return NULL; - -	spin_lock_irqsave(&iommu_pd_list_lock, flags); - -	list_for_each_entry(entry, &iommu_pd_list, list) { -		if (entry->target_dev == devid) { -			ret = entry; -			break; -		} -	} - -	spin_unlock_irqrestore(&iommu_pd_list_lock, flags); - -	return ret; -} - -/*   * In the dma_ops path we only have the struct device. This function   * finds the corresponding IOMMU, the protection domain and the   * requestor id for a given device.   * If the device is not yet associated with a domain this is also done   * in this function.   */ -static int get_device_resources(struct device *dev, -				struct amd_iommu **iommu, -				struct protection_domain **domain, -				u16 *bdf) +static struct protection_domain *get_domain(struct device *dev)  { +	struct protection_domain *domain;  	struct dma_ops_domain *dma_dom; -	struct pci_dev *pcidev; -	u16 _bdf; - -	*iommu = NULL; -	*domain = NULL; -	*bdf = 0xffff; - -	if (dev->bus != &pci_bus_type) -		return 0; +	u16 devid = get_device_id(dev); -	pcidev = to_pci_dev(dev); -	_bdf = calc_devid(pcidev->bus->number, pcidev->devfn); +	if (!check_device(dev)) +		return ERR_PTR(-EINVAL); -	/* device not translated by any IOMMU in the system? */ -	if (_bdf > amd_iommu_last_bdf) -		return 0; +	domain = domain_for_device(dev); +	if (domain != NULL && !dma_ops_domain(domain)) +		return ERR_PTR(-EBUSY); -	*bdf = amd_iommu_alias_table[_bdf]; +	if (domain != NULL) +		return domain; -	*iommu = amd_iommu_rlookup_table[*bdf]; -	if (*iommu == NULL) -		return 0; -	*domain = domain_for_device(*bdf); -	if (*domain == NULL) { -		dma_dom = find_protection_domain(*bdf); -		if (!dma_dom) -			dma_dom = (*iommu)->default_dom; -		*domain = &dma_dom->domain; -		attach_device(*iommu, *domain, *bdf); -		DUMP_printk("Using protection domain %d for device %s\n", -			    (*domain)->id, dev_name(dev)); -	} - -	if (domain_for_device(_bdf) == NULL) -		attach_device(*iommu, *domain, _bdf); +	/* Device not bount yet - bind it */ +	dma_dom = find_protection_domain(devid); +	if (!dma_dom) +		dma_dom = amd_iommu_rlookup_table[devid]->default_dom; +	attach_device(dev, &dma_dom->domain); +	DUMP_printk("Using protection domain %d for device %s\n", +		    dma_dom->domain.id, dev_name(dev)); -	return 1; +	return &dma_dom->domain;  }  static void update_device_table(struct protection_domain *domain)  { -	unsigned long flags; -	int i; +	struct iommu_dev_data *dev_data; -	for (i = 0; i <= amd_iommu_last_bdf; ++i) { -		if (amd_iommu_pd_table[i] != domain) -			continue; -		write_lock_irqsave(&amd_iommu_devtable_lock, flags); -		set_dte_entry(i, domain); -		write_unlock_irqrestore(&amd_iommu_devtable_lock, flags); +	list_for_each_entry(dev_data, &domain->dev_list, list) { +		u16 devid = get_device_id(dev_data->dev); +		set_dte_entry(devid, domain);  	}  } @@ -1431,76 +1643,13 @@ static void update_domain(struct protection_domain *domain)  		return;  	update_device_table(domain); -	flush_devices_by_domain(domain); -	iommu_flush_domain(domain->id); +	iommu_flush_domain_devices(domain); +	iommu_flush_tlb_pde(domain);  	domain->updated = false;  }  /* - * This function is used to add another level to an IO page table. Adding - * another level increases the size of the address space by 9 bits to a size up - * to 64 bits. - */ -static bool increase_address_space(struct protection_domain *domain, -				   gfp_t gfp) -{ -	u64 *pte; - -	if (domain->mode == PAGE_MODE_6_LEVEL) -		/* address space already 64 bit large */ -		return false; - -	pte = (void *)get_zeroed_page(gfp); -	if (!pte) -		return false; - -	*pte             = PM_LEVEL_PDE(domain->mode, -					virt_to_phys(domain->pt_root)); -	domain->pt_root  = pte; -	domain->mode    += 1; -	domain->updated  = true; - -	return true; -} - -static u64 *alloc_pte(struct protection_domain *domain, -		      unsigned long address, -		      int end_lvl, -		      u64 **pte_page, -		      gfp_t gfp) -{ -	u64 *pte, *page; -	int level; - -	while (address > PM_LEVEL_SIZE(domain->mode)) -		increase_address_space(domain, gfp); - -	level =  domain->mode - 1; -	pte   = &domain->pt_root[PM_LEVEL_INDEX(level, address)]; - -	while (level > end_lvl) { -		if (!IOMMU_PTE_PRESENT(*pte)) { -			page = (u64 *)get_zeroed_page(gfp); -			if (!page) -				return NULL; -			*pte = PM_LEVEL_PDE(level, virt_to_phys(page)); -		} - -		level -= 1; - -		pte = IOMMU_PTE_PAGE(*pte); - -		if (pte_page && level == end_lvl) -			*pte_page = pte; - -		pte = &pte[PM_LEVEL_INDEX(level, address)]; -	} - -	return pte; -} - -/*   * This function fetches the PTE for a given address in the aperture   */  static u64* dma_ops_get_pte(struct dma_ops_domain *dom, @@ -1530,8 +1679,7 @@ static u64* dma_ops_get_pte(struct dma_ops_domain *dom,   * This is the generic map function. It maps one 4kb page at paddr to   * the given address in the DMA address space for the domain.   */ -static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu, -				     struct dma_ops_domain *dom, +static dma_addr_t dma_ops_domain_map(struct dma_ops_domain *dom,  				     unsigned long address,  				     phys_addr_t paddr,  				     int direction) @@ -1544,7 +1692,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,  	pte  = dma_ops_get_pte(dom, address);  	if (!pte) -		return bad_dma_address; +		return DMA_ERROR_CODE;  	__pte = paddr | IOMMU_PTE_P | IOMMU_PTE_FC; @@ -1565,8 +1713,7 @@ static dma_addr_t dma_ops_domain_map(struct amd_iommu *iommu,  /*   * The generic unmapping function for on page in the DMA address space.   */ -static void dma_ops_domain_unmap(struct amd_iommu *iommu, -				 struct dma_ops_domain *dom, +static void dma_ops_domain_unmap(struct dma_ops_domain *dom,  				 unsigned long address)  {  	struct aperture_range *aperture; @@ -1597,7 +1744,6 @@ static void dma_ops_domain_unmap(struct amd_iommu *iommu,   * Must be called with the domain lock held.   */  static dma_addr_t __map_single(struct device *dev, -			       struct amd_iommu *iommu,  			       struct dma_ops_domain *dma_dom,  			       phys_addr_t paddr,  			       size_t size, @@ -1625,7 +1771,7 @@ static dma_addr_t __map_single(struct device *dev,  retry:  	address = dma_ops_alloc_addresses(dev, dma_dom, pages, align_mask,  					  dma_mask); -	if (unlikely(address == bad_dma_address)) { +	if (unlikely(address == DMA_ERROR_CODE)) {  		/*  		 * setting next_address here will let the address  		 * allocator only scan the new allocated range in the @@ -1633,7 +1779,7 @@ retry:  		 */  		dma_dom->next_address = dma_dom->aperture_size; -		if (alloc_new_range(iommu, dma_dom, false, GFP_ATOMIC)) +		if (alloc_new_range(dma_dom, false, GFP_ATOMIC))  			goto out;  		/* @@ -1645,8 +1791,8 @@ retry:  	start = address;  	for (i = 0; i < pages; ++i) { -		ret = dma_ops_domain_map(iommu, dma_dom, start, paddr, dir); -		if (ret == bad_dma_address) +		ret = dma_ops_domain_map(dma_dom, start, paddr, dir); +		if (ret == DMA_ERROR_CODE)  			goto out_unmap;  		paddr += PAGE_SIZE; @@ -1657,10 +1803,10 @@ retry:  	ADD_STATS_COUNTER(alloced_io_mem, size);  	if (unlikely(dma_dom->need_flush && !amd_iommu_unmap_flush)) { -		iommu_flush_tlb(iommu, dma_dom->domain.id); +		iommu_flush_tlb(&dma_dom->domain);  		dma_dom->need_flush = false; -	} else if (unlikely(iommu_has_npcache(iommu))) -		iommu_flush_pages(iommu, dma_dom->domain.id, address, size); +	} else if (unlikely(amd_iommu_np_cache)) +		iommu_flush_pages(&dma_dom->domain, address, size);  out:  	return address; @@ -1669,20 +1815,19 @@ out_unmap:  	for (--i; i >= 0; --i) {  		start -= PAGE_SIZE; -		dma_ops_domain_unmap(iommu, dma_dom, start); +		dma_ops_domain_unmap(dma_dom, start);  	}  	dma_ops_free_addresses(dma_dom, address, pages); -	return bad_dma_address; +	return DMA_ERROR_CODE;  }  /*   * Does the reverse of the __map_single function. Must be called with   * the domain lock held too   */ -static void __unmap_single(struct amd_iommu *iommu, -			   struct dma_ops_domain *dma_dom, +static void __unmap_single(struct dma_ops_domain *dma_dom,  			   dma_addr_t dma_addr,  			   size_t size,  			   int dir) @@ -1690,7 +1835,7 @@ static void __unmap_single(struct amd_iommu *iommu,  	dma_addr_t i, start;  	unsigned int pages; -	if ((dma_addr == bad_dma_address) || +	if ((dma_addr == DMA_ERROR_CODE) ||  	    (dma_addr + size > dma_dom->aperture_size))  		return; @@ -1699,7 +1844,7 @@ static void __unmap_single(struct amd_iommu *iommu,  	start = dma_addr;  	for (i = 0; i < pages; ++i) { -		dma_ops_domain_unmap(iommu, dma_dom, start); +		dma_ops_domain_unmap(dma_dom, start);  		start += PAGE_SIZE;  	} @@ -1708,7 +1853,7 @@ static void __unmap_single(struct amd_iommu *iommu,  	dma_ops_free_addresses(dma_dom, dma_addr, pages);  	if (amd_iommu_unmap_flush || dma_dom->need_flush) { -		iommu_flush_pages(iommu, dma_dom->domain.id, dma_addr, size); +		iommu_flush_pages(&dma_dom->domain, dma_addr, size);  		dma_dom->need_flush = false;  	}  } @@ -1722,36 +1867,29 @@ static dma_addr_t map_page(struct device *dev, struct page *page,  			   struct dma_attrs *attrs)  {  	unsigned long flags; -	struct amd_iommu *iommu;  	struct protection_domain *domain; -	u16 devid;  	dma_addr_t addr;  	u64 dma_mask;  	phys_addr_t paddr = page_to_phys(page) + offset;  	INC_STATS_COUNTER(cnt_map_single); -	if (!check_device(dev)) -		return bad_dma_address; - -	dma_mask = *dev->dma_mask; - -	get_device_resources(dev, &iommu, &domain, &devid); - -	if (iommu == NULL || domain == NULL) -		/* device not handled by any AMD IOMMU */ +	domain = get_domain(dev); +	if (PTR_ERR(domain) == -EINVAL)  		return (dma_addr_t)paddr; +	else if (IS_ERR(domain)) +		return DMA_ERROR_CODE; -	if (!dma_ops_domain(domain)) -		return bad_dma_address; +	dma_mask = *dev->dma_mask;  	spin_lock_irqsave(&domain->lock, flags); -	addr = __map_single(dev, iommu, domain->priv, paddr, size, dir, false, + +	addr = __map_single(dev, domain->priv, paddr, size, dir, false,  			    dma_mask); -	if (addr == bad_dma_address) +	if (addr == DMA_ERROR_CODE)  		goto out; -	iommu_completion_wait(iommu); +	iommu_flush_complete(domain);  out:  	spin_unlock_irqrestore(&domain->lock, flags); @@ -1766,25 +1904,19 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,  		       enum dma_data_direction dir, struct dma_attrs *attrs)  {  	unsigned long flags; -	struct amd_iommu *iommu;  	struct protection_domain *domain; -	u16 devid;  	INC_STATS_COUNTER(cnt_unmap_single); -	if (!check_device(dev) || -	    !get_device_resources(dev, &iommu, &domain, &devid)) -		/* device not handled by any AMD IOMMU */ -		return; - -	if (!dma_ops_domain(domain)) +	domain = get_domain(dev); +	if (IS_ERR(domain))  		return;  	spin_lock_irqsave(&domain->lock, flags); -	__unmap_single(iommu, domain->priv, dma_addr, size, dir); +	__unmap_single(domain->priv, dma_addr, size, dir); -	iommu_completion_wait(iommu); +	iommu_flush_complete(domain);  	spin_unlock_irqrestore(&domain->lock, flags);  } @@ -1816,9 +1948,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,  		  struct dma_attrs *attrs)  {  	unsigned long flags; -	struct amd_iommu *iommu;  	struct protection_domain *domain; -	u16 devid;  	int i;  	struct scatterlist *s;  	phys_addr_t paddr; @@ -1827,25 +1957,20 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,  	INC_STATS_COUNTER(cnt_map_sg); -	if (!check_device(dev)) +	domain = get_domain(dev); +	if (PTR_ERR(domain) == -EINVAL) +		return map_sg_no_iommu(dev, sglist, nelems, dir); +	else if (IS_ERR(domain))  		return 0;  	dma_mask = *dev->dma_mask; -	get_device_resources(dev, &iommu, &domain, &devid); - -	if (!iommu || !domain) -		return map_sg_no_iommu(dev, sglist, nelems, dir); - -	if (!dma_ops_domain(domain)) -		return 0; -  	spin_lock_irqsave(&domain->lock, flags);  	for_each_sg(sglist, s, nelems, i) {  		paddr = sg_phys(s); -		s->dma_address = __map_single(dev, iommu, domain->priv, +		s->dma_address = __map_single(dev, domain->priv,  					      paddr, s->length, dir, false,  					      dma_mask); @@ -1856,7 +1981,7 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,  			goto unmap;  	} -	iommu_completion_wait(iommu); +	iommu_flush_complete(domain);  out:  	spin_unlock_irqrestore(&domain->lock, flags); @@ -1865,7 +1990,7 @@ out:  unmap:  	for_each_sg(sglist, s, mapped_elems, i) {  		if (s->dma_address) -			__unmap_single(iommu, domain->priv, s->dma_address, +			__unmap_single(domain->priv, s->dma_address,  				       s->dma_length, dir);  		s->dma_address = s->dma_length = 0;  	} @@ -1884,30 +2009,25 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist,  		     struct dma_attrs *attrs)  {  	unsigned long flags; -	struct amd_iommu *iommu;  	struct protection_domain *domain;  	struct scatterlist *s; -	u16 devid;  	int i;  	INC_STATS_COUNTER(cnt_unmap_sg); -	if (!check_device(dev) || -	    !get_device_resources(dev, &iommu, &domain, &devid)) -		return; - -	if (!dma_ops_domain(domain)) +	domain = get_domain(dev); +	if (IS_ERR(domain))  		return;  	spin_lock_irqsave(&domain->lock, flags);  	for_each_sg(sglist, s, nelems, i) { -		__unmap_single(iommu, domain->priv, s->dma_address, +		__unmap_single(domain->priv, s->dma_address,  			       s->dma_length, dir);  		s->dma_address = s->dma_length = 0;  	} -	iommu_completion_wait(iommu); +	iommu_flush_complete(domain);  	spin_unlock_irqrestore(&domain->lock, flags);  } @@ -1920,49 +2040,44 @@ static void *alloc_coherent(struct device *dev, size_t size,  {  	unsigned long flags;  	void *virt_addr; -	struct amd_iommu *iommu;  	struct protection_domain *domain; -	u16 devid;  	phys_addr_t paddr;  	u64 dma_mask = dev->coherent_dma_mask;  	INC_STATS_COUNTER(cnt_alloc_coherent); -	if (!check_device(dev)) +	domain = get_domain(dev); +	if (PTR_ERR(domain) == -EINVAL) { +		virt_addr = (void *)__get_free_pages(flag, get_order(size)); +		*dma_addr = __pa(virt_addr); +		return virt_addr; +	} else if (IS_ERR(domain))  		return NULL; -	if (!get_device_resources(dev, &iommu, &domain, &devid)) -		flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); +	dma_mask  = dev->coherent_dma_mask; +	flag     &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32); +	flag     |= __GFP_ZERO; -	flag |= __GFP_ZERO;  	virt_addr = (void *)__get_free_pages(flag, get_order(size));  	if (!virt_addr)  		return NULL;  	paddr = virt_to_phys(virt_addr); -	if (!iommu || !domain) { -		*dma_addr = (dma_addr_t)paddr; -		return virt_addr; -	} - -	if (!dma_ops_domain(domain)) -		goto out_free; -  	if (!dma_mask)  		dma_mask = *dev->dma_mask;  	spin_lock_irqsave(&domain->lock, flags); -	*dma_addr = __map_single(dev, iommu, domain->priv, paddr, +	*dma_addr = __map_single(dev, domain->priv, paddr,  				 size, DMA_BIDIRECTIONAL, true, dma_mask); -	if (*dma_addr == bad_dma_address) { +	if (*dma_addr == DMA_ERROR_CODE) {  		spin_unlock_irqrestore(&domain->lock, flags);  		goto out_free;  	} -	iommu_completion_wait(iommu); +	iommu_flush_complete(domain);  	spin_unlock_irqrestore(&domain->lock, flags); @@ -1982,28 +2097,19 @@ static void free_coherent(struct device *dev, size_t size,  			  void *virt_addr, dma_addr_t dma_addr)  {  	unsigned long flags; -	struct amd_iommu *iommu;  	struct protection_domain *domain; -	u16 devid;  	INC_STATS_COUNTER(cnt_free_coherent); -	if (!check_device(dev)) -		return; - -	get_device_resources(dev, &iommu, &domain, &devid); - -	if (!iommu || !domain) -		goto free_mem; - -	if (!dma_ops_domain(domain)) +	domain = get_domain(dev); +	if (IS_ERR(domain))  		goto free_mem;  	spin_lock_irqsave(&domain->lock, flags); -	__unmap_single(iommu, domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); +	__unmap_single(domain->priv, dma_addr, size, DMA_BIDIRECTIONAL); -	iommu_completion_wait(iommu); +	iommu_flush_complete(domain);  	spin_unlock_irqrestore(&domain->lock, flags); @@ -2017,22 +2123,7 @@ free_mem:   */  static int amd_iommu_dma_supported(struct device *dev, u64 mask)  { -	u16 bdf; -	struct pci_dev *pcidev; - -	/* No device or no PCI device */ -	if (!dev || dev->bus != &pci_bus_type) -		return 0; - -	pcidev = to_pci_dev(dev); - -	bdf = calc_devid(pcidev->bus->number, pcidev->devfn); - -	/* Out of our scope? */ -	if (bdf > amd_iommu_last_bdf) -		return 0; - -	return 1; +	return check_device(dev);  }  /* @@ -2046,25 +2137,30 @@ static void prealloc_protection_domains(void)  {  	struct pci_dev *dev = NULL;  	struct dma_ops_domain *dma_dom; -	struct amd_iommu *iommu;  	u16 devid;  	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { -		devid = calc_devid(dev->bus->number, dev->devfn); -		if (devid > amd_iommu_last_bdf) -			continue; -		devid = amd_iommu_alias_table[devid]; -		if (domain_for_device(devid)) + +		/* Do we handle this device? */ +		if (!check_device(&dev->dev))  			continue; -		iommu = amd_iommu_rlookup_table[devid]; -		if (!iommu) + +		iommu_init_device(&dev->dev); + +		/* Is there already any domain for it? */ +		if (domain_for_device(&dev->dev))  			continue; -		dma_dom = dma_ops_domain_alloc(iommu); + +		devid = get_device_id(&dev->dev); + +		dma_dom = dma_ops_domain_alloc();  		if (!dma_dom)  			continue;  		init_unity_mappings_for_device(dma_dom, devid);  		dma_dom->target_dev = devid; +		attach_device(&dev->dev, &dma_dom->domain); +  		list_add_tail(&dma_dom->list, &iommu_pd_list);  	}  } @@ -2093,7 +2189,7 @@ int __init amd_iommu_init_dma_ops(void)  	 * protection domain will be assigned to the default one.  	 */  	for_each_iommu(iommu) { -		iommu->default_dom = dma_ops_domain_alloc(iommu); +		iommu->default_dom = dma_ops_domain_alloc();  		if (iommu->default_dom == NULL)  			return -ENOMEM;  		iommu->default_dom->domain.flags |= PD_DEFAULT_MASK; @@ -2103,15 +2199,12 @@ int __init amd_iommu_init_dma_ops(void)  	}  	/* -	 * If device isolation is enabled, pre-allocate the protection -	 * domains for each device. +	 * Pre-allocate the protection domains for each device.  	 */ -	if (amd_iommu_isolate) -		prealloc_protection_domains(); +	prealloc_protection_domains();  	iommu_detected = 1; -	force_iommu = 1; -	bad_dma_address = 0; +	swiotlb = 0;  #ifdef CONFIG_GART_IOMMU  	gart_iommu_aperture_disabled = 1;  	gart_iommu_aperture = 0; @@ -2150,14 +2243,17 @@ free_domains:  static void cleanup_domain(struct protection_domain *domain)  { +	struct iommu_dev_data *dev_data, *next;  	unsigned long flags; -	u16 devid;  	write_lock_irqsave(&amd_iommu_devtable_lock, flags); -	for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) -		if (amd_iommu_pd_table[devid] == domain) -			__detach_device(domain, devid); +	list_for_each_entry_safe(dev_data, next, &domain->dev_list, list) { +		struct device *dev = dev_data->dev; + +		do_detach(dev); +		atomic_set(&dev_data->bind, 0); +	}  	write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);  } @@ -2167,6 +2263,8 @@ static void protection_domain_free(struct protection_domain *domain)  	if (!domain)  		return; +	del_domain_from_list(domain); +  	if (domain->id)  		domain_id_free(domain->id); @@ -2185,6 +2283,9 @@ static struct protection_domain *protection_domain_alloc(void)  	domain->id = domain_id_alloc();  	if (!domain->id)  		goto out_err; +	INIT_LIST_HEAD(&domain->dev_list); + +	add_domain_to_list(domain);  	return domain; @@ -2241,26 +2342,23 @@ static void amd_iommu_domain_destroy(struct iommu_domain *dom)  static void amd_iommu_detach_device(struct iommu_domain *dom,  				    struct device *dev)  { -	struct protection_domain *domain = dom->priv; +	struct iommu_dev_data *dev_data = dev->archdata.iommu;  	struct amd_iommu *iommu; -	struct pci_dev *pdev;  	u16 devid; -	if (dev->bus != &pci_bus_type) +	if (!check_device(dev))  		return; -	pdev = to_pci_dev(dev); - -	devid = calc_devid(pdev->bus->number, pdev->devfn); +	devid = get_device_id(dev); -	if (devid > 0) -		detach_device(domain, devid); +	if (dev_data->domain != NULL) +		detach_device(dev);  	iommu = amd_iommu_rlookup_table[devid];  	if (!iommu)  		return; -	iommu_queue_inv_dev_entry(iommu, devid); +	iommu_flush_device(dev);  	iommu_completion_wait(iommu);  } @@ -2268,35 +2366,30 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,  				   struct device *dev)  {  	struct protection_domain *domain = dom->priv; -	struct protection_domain *old_domain; +	struct iommu_dev_data *dev_data;  	struct amd_iommu *iommu; -	struct pci_dev *pdev; +	int ret;  	u16 devid; -	if (dev->bus != &pci_bus_type) +	if (!check_device(dev))  		return -EINVAL; -	pdev = to_pci_dev(dev); +	dev_data = dev->archdata.iommu; -	devid = calc_devid(pdev->bus->number, pdev->devfn); - -	if (devid >= amd_iommu_last_bdf || -			devid != amd_iommu_alias_table[devid]) -		return -EINVAL; +	devid = get_device_id(dev);  	iommu = amd_iommu_rlookup_table[devid];  	if (!iommu)  		return -EINVAL; -	old_domain = domain_for_device(devid); -	if (old_domain) -		detach_device(old_domain, devid); +	if (dev_data->domain) +		detach_device(dev); -	attach_device(iommu, domain, devid); +	ret = attach_device(dev, domain);  	iommu_completion_wait(iommu); -	return 0; +	return ret;  }  static int amd_iommu_map_range(struct iommu_domain *dom, @@ -2342,7 +2435,7 @@ static void amd_iommu_unmap_range(struct iommu_domain *dom,  		iova  += PAGE_SIZE;  	} -	iommu_flush_domain(domain->id); +	iommu_flush_tlb_pde(domain);  }  static phys_addr_t amd_iommu_iova_to_phys(struct iommu_domain *dom, @@ -2393,8 +2486,9 @@ static struct iommu_ops amd_iommu_ops = {  int __init amd_iommu_init_passthrough(void)  { +	struct amd_iommu *iommu;  	struct pci_dev *dev = NULL; -	u16 devid, devid2; +	u16 devid;  	/* allocate passthroug domain */  	pt_domain = protection_domain_alloc(); @@ -2404,20 +2498,17 @@ int __init amd_iommu_init_passthrough(void)  	pt_domain->mode |= PAGE_MODE_NONE;  	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { -		struct amd_iommu *iommu; -		devid = calc_devid(dev->bus->number, dev->devfn); -		if (devid > amd_iommu_last_bdf) +		if (!check_device(&dev->dev))  			continue; -		devid2 = amd_iommu_alias_table[devid]; +		devid = get_device_id(&dev->dev); -		iommu = amd_iommu_rlookup_table[devid2]; +		iommu = amd_iommu_rlookup_table[devid];  		if (!iommu)  			continue; -		__attach_device(iommu, pt_domain, devid); -		__attach_device(iommu, pt_domain, devid2); +		attach_device(&dev->dev, pt_domain);  	}  	pr_info("AMD-Vi: Initialized for Passthrough Mode\n"); diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index c20001e4f55..7ffc3996523 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c @@ -1,5 +1,5 @@  /* - * Copyright (C) 2007-2008 Advanced Micro Devices, Inc. + * Copyright (C) 2007-2009 Advanced Micro Devices, Inc.   * Author: Joerg Roedel <joerg.roedel@amd.com>   *         Leo Duran <leo.duran@amd.com>   * @@ -25,10 +25,12 @@  #include <linux/interrupt.h>  #include <linux/msi.h>  #include <asm/pci-direct.h> +#include <asm/amd_iommu_proto.h>  #include <asm/amd_iommu_types.h>  #include <asm/amd_iommu.h>  #include <asm/iommu.h>  #include <asm/gart.h> +#include <asm/x86_init.h>  /*   * definitions for the ACPI scanning code @@ -123,18 +125,24 @@ u16 amd_iommu_last_bdf;			/* largest PCI device id we have  					   to handle */  LIST_HEAD(amd_iommu_unity_map);		/* a list of required unity mappings  					   we find in ACPI */ -#ifdef CONFIG_IOMMU_STRESS -bool amd_iommu_isolate = false; -#else -bool amd_iommu_isolate = true;		/* if true, device isolation is -					   enabled */ -#endif -  bool amd_iommu_unmap_flush;		/* if true, flush on every unmap */  LIST_HEAD(amd_iommu_list);		/* list of all AMD IOMMUs in the  					   system */ +/* Array to assign indices to IOMMUs*/ +struct amd_iommu *amd_iommus[MAX_IOMMUS]; +int amd_iommus_present; + +/* IOMMUs have a non-present cache? */ +bool amd_iommu_np_cache __read_mostly; + +/* + * List of protection domains - used during resume + */ +LIST_HEAD(amd_iommu_pd_list); +spinlock_t amd_iommu_pd_lock; +  /*   * Pointer to the device table which is shared by all AMD IOMMUs   * it is indexed by the PCI device id or the HT unit id and contains @@ -157,12 +165,6 @@ u16 *amd_iommu_alias_table;  struct amd_iommu **amd_iommu_rlookup_table;  /* - * The pd table (protection domain table) is used to find the protection domain - * data structure a device belongs to. Indexed with the PCI device id too. - */ -struct protection_domain **amd_iommu_pd_table; - -/*   * AMD IOMMU allows up to 2^16 differend protection domains. This is a bitmap   * to know which ones are already in use.   */ @@ -838,7 +840,18 @@ static void __init free_iommu_all(void)  static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)  {  	spin_lock_init(&iommu->lock); + +	/* Add IOMMU to internal data structures */  	list_add_tail(&iommu->list, &amd_iommu_list); +	iommu->index             = amd_iommus_present++; + +	if (unlikely(iommu->index >= MAX_IOMMUS)) { +		WARN(1, "AMD-Vi: System has more IOMMUs than supported by this driver\n"); +		return -ENOSYS; +	} + +	/* Index is fine - add IOMMU to the array */ +	amd_iommus[iommu->index] = iommu;  	/*  	 * Copy data from ACPI table entry to the iommu struct @@ -868,6 +881,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)  	init_iommu_from_acpi(iommu, h);  	init_iommu_devices(iommu); +	if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) +		amd_iommu_np_cache = true; +  	return pci_enable_device(iommu->dev);  } @@ -925,7 +941,7 @@ static int __init init_iommu_all(struct acpi_table_header *table)   *   ****************************************************************************/ -static int __init iommu_setup_msi(struct amd_iommu *iommu) +static int iommu_setup_msi(struct amd_iommu *iommu)  {  	int r; @@ -1176,19 +1192,10 @@ static struct sys_device device_amd_iommu = {   * functions. Finally it prints some information about AMD IOMMUs and   * the driver state and enables the hardware.   */ -int __init amd_iommu_init(void) +static int __init amd_iommu_init(void)  {  	int i, ret = 0; - -	if (no_iommu) { -		printk(KERN_INFO "AMD-Vi disabled by kernel command line\n"); -		return 0; -	} - -	if (!amd_iommu_detected) -		return -ENODEV; -  	/*  	 * First parse ACPI tables to find the largest Bus/Dev/Func  	 * we need to handle. Upon this information the shared data @@ -1225,15 +1232,6 @@ int __init amd_iommu_init(void)  	if (amd_iommu_rlookup_table == NULL)  		goto free; -	/* -	 * Protection Domain table - maps devices to protection domains -	 * This table has the same size as the rlookup_table -	 */ -	amd_iommu_pd_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, -				     get_order(rlookup_table_size)); -	if (amd_iommu_pd_table == NULL) -		goto free; -  	amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages(  					    GFP_KERNEL | __GFP_ZERO,  					    get_order(MAX_DOMAIN_ID/8)); @@ -1255,6 +1253,8 @@ int __init amd_iommu_init(void)  	 */  	amd_iommu_pd_alloc_bitmap[0] = 1; +	spin_lock_init(&amd_iommu_pd_lock); +  	/*  	 * now the data structures are allocated and basically initialized  	 * start the real acpi table scan @@ -1286,17 +1286,12 @@ int __init amd_iommu_init(void)  	if (iommu_pass_through)  		goto out; -	printk(KERN_INFO "AMD-Vi: device isolation "); -	if (amd_iommu_isolate) -		printk("enabled\n"); -	else -		printk("disabled\n"); -  	if (amd_iommu_unmap_flush)  		printk(KERN_INFO "AMD-Vi: IO/TLB flush on unmap enabled\n");  	else  		printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); +	x86_platform.iommu_shutdown = disable_iommus;  out:  	return ret; @@ -1304,9 +1299,6 @@ free:  	free_pages((unsigned long)amd_iommu_pd_alloc_bitmap,  		   get_order(MAX_DOMAIN_ID/8)); -	free_pages((unsigned long)amd_iommu_pd_table, -		   get_order(rlookup_table_size)); -  	free_pages((unsigned long)amd_iommu_rlookup_table,  		   get_order(rlookup_table_size)); @@ -1323,11 +1315,6 @@ free:  	goto out;  } -void amd_iommu_shutdown(void) -{ -	disable_iommus(); -} -  /****************************************************************************   *   * Early detect code. This code runs at IOMMU detection time in the DMA @@ -1342,16 +1329,13 @@ static int __init early_amd_iommu_detect(struct acpi_table_header *table)  void __init amd_iommu_detect(void)  { -	if (swiotlb || no_iommu || (iommu_detected && !gart_iommu_aperture)) +	if (no_iommu || (iommu_detected && !gart_iommu_aperture))  		return;  	if (acpi_table_parse("IVRS", early_amd_iommu_detect) == 0) {  		iommu_detected = 1;  		amd_iommu_detected = 1; -#ifdef CONFIG_GART_IOMMU -		gart_iommu_aperture_disabled = 1; -		gart_iommu_aperture = 0; -#endif +		x86_init.iommu.iommu_init = amd_iommu_init;  	}  } @@ -1372,10 +1356,6 @@ static int __init parse_amd_iommu_dump(char *str)  static int __init parse_amd_iommu_options(char *str)  {  	for (; *str; ++str) { -		if (strncmp(str, "isolate", 7) == 0) -			amd_iommu_isolate = true; -		if (strncmp(str, "share", 5) == 0) -			amd_iommu_isolate = false;  		if (strncmp(str, "fullflush", 9) == 0)  			amd_iommu_unmap_flush = true;  	} diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c index 128111d8ffe..e0dfb6856aa 100644 --- a/arch/x86/kernel/aperture_64.c +++ b/arch/x86/kernel/aperture_64.c @@ -28,6 +28,7 @@  #include <asm/pci-direct.h>  #include <asm/dma.h>  #include <asm/k8.h> +#include <asm/x86_init.h>  int gart_iommu_aperture;  int gart_iommu_aperture_disabled __initdata; @@ -400,6 +401,7 @@ void __init gart_iommu_hole_init(void)  			iommu_detected = 1;  			gart_iommu_aperture = 1; +			x86_init.iommu.iommu_init = gart_iommu_init;  			aper_order = (read_pci_config(bus, slot, 3, AMD64_GARTAPERTURECTL) >> 1) & 7;  			aper_size = (32 * 1024 * 1024) << aper_order; @@ -456,7 +458,7 @@ out:  	if (aper_alloc) {  		/* Got the aperture from the AGP bridge */ -	} else if (swiotlb && !valid_agp) { +	} else if (!valid_agp) {  		/* Do nothing */  	} else if ((!no_iommu && max_pfn > MAX_DMA32_PFN) ||  		   force_iommu || diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 5e409dc298a..a4849c10a77 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -27,8 +27,7 @@  #include <asm/cpu.h>  #include <asm/reboot.h>  #include <asm/virtext.h> -#include <asm/iommu.h> - +#include <asm/x86_init.h>  #if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC) @@ -106,7 +105,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)  #endif  #ifdef CONFIG_X86_64 -	pci_iommu_shutdown(); +	x86_platform.iommu_shutdown();  #endif  	crash_save_cpu(regs, safe_smp_processor_id()); diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index c097e7d607c..7d52e9da5e0 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1185,17 +1185,14 @@ END(ftrace_graph_caller)  .globl return_to_handler  return_to_handler: -	pushl $0  	pushl %eax -	pushl %ecx  	pushl %edx  	movl %ebp, %eax  	call ftrace_return_to_handler -	movl %eax, 0xc(%esp) +	movl %eax, %ecx  	popl %edx -	popl %ecx  	popl %eax -	ret +	jmp *%ecx  #endif  .section .rodata,"a" diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index b5c061f8f35..bd5bbddddf9 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -155,11 +155,11 @@ GLOBAL(return_to_handler)  	call ftrace_return_to_handler -	movq %rax, 16(%rsp) +	movq %rax, %rdi  	movq 8(%rsp), %rdx  	movq (%rsp), %rax -	addq $16, %rsp -	retq +	addq $24, %rsp +	jmp *%rdi  #endif diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 9dbb527e165..5a1b9758fd6 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -9,6 +9,8 @@   * the dangers of modifying code on the run.   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/spinlock.h>  #include <linux/hardirq.h>  #include <linux/uaccess.h> @@ -336,15 +338,15 @@ int __init ftrace_dyn_arch_init(void *data)  	switch (faulted) {  	case 0: -		pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n"); +		pr_info("converting mcount calls to 0f 1f 44 00 00\n");  		memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);  		break;  	case 1: -		pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n"); +		pr_info("converting mcount calls to 66 66 66 66 90\n");  		memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);  		break;  	case 2: -		pr_info("ftrace: converting mcount calls to jmp . + 5\n"); +		pr_info("converting mcount calls to jmp . + 5\n");  		memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);  		break;  	} @@ -468,82 +470,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,  #ifdef CONFIG_FTRACE_SYSCALLS -extern unsigned long __start_syscalls_metadata[]; -extern unsigned long __stop_syscalls_metadata[];  extern unsigned long *sys_call_table; -static struct syscall_metadata **syscalls_metadata; - -static struct syscall_metadata *find_syscall_meta(unsigned long *syscall) -{ -	struct syscall_metadata *start; -	struct syscall_metadata *stop; -	char str[KSYM_SYMBOL_LEN]; - - -	start = (struct syscall_metadata *)__start_syscalls_metadata; -	stop = (struct syscall_metadata *)__stop_syscalls_metadata; -	kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str); - -	for ( ; start < stop; start++) { -		if (start->name && !strcmp(start->name, str)) -			return start; -	} -	return NULL; -} - -struct syscall_metadata *syscall_nr_to_meta(int nr) -{ -	if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) -		return NULL; - -	return syscalls_metadata[nr]; -} - -int syscall_name_to_nr(char *name) +unsigned long __init arch_syscall_addr(int nr)  { -	int i; - -	if (!syscalls_metadata) -		return -1; - -	for (i = 0; i < NR_syscalls; i++) { -		if (syscalls_metadata[i]) { -			if (!strcmp(syscalls_metadata[i]->name, name)) -				return i; -		} -	} -	return -1; -} - -void set_syscall_enter_id(int num, int id) -{ -	syscalls_metadata[num]->enter_id = id; -} - -void set_syscall_exit_id(int num, int id) -{ -	syscalls_metadata[num]->exit_id = id; -} - -static int __init arch_init_ftrace_syscalls(void) -{ -	int i; -	struct syscall_metadata *meta; -	unsigned long **psys_syscall_table = &sys_call_table; - -	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * -					NR_syscalls, GFP_KERNEL); -	if (!syscalls_metadata) { -		WARN_ON(1); -		return -ENOMEM; -	} - -	for (i = 0; i < NR_syscalls; i++) { -		meta = find_syscall_meta(psys_syscall_table[i]); -		syscalls_metadata[i] = meta; -	} -	return 0; +	return (unsigned long)(&sys_call_table)[nr];  } -arch_initcall(arch_init_ftrace_syscalls);  #endif diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c index 971a3bec47a..c563e4c8ff3 100644 --- a/arch/x86/kernel/pci-calgary_64.c +++ b/arch/x86/kernel/pci-calgary_64.c @@ -46,6 +46,7 @@  #include <asm/dma.h>  #include <asm/rio.h>  #include <asm/bios_ebda.h> +#include <asm/x86_init.h>  #ifdef CONFIG_CALGARY_IOMMU_ENABLED_BY_DEFAULT  int use_calgary __read_mostly = 1; @@ -244,7 +245,7 @@ static unsigned long iommu_range_alloc(struct device *dev,  			if (panic_on_overflow)  				panic("Calgary: fix the allocator.\n");  			else -				return bad_dma_address; +				return DMA_ERROR_CODE;  		}  	} @@ -260,12 +261,15 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,  			      void *vaddr, unsigned int npages, int direction)  {  	unsigned long entry; -	dma_addr_t ret = bad_dma_address; +	dma_addr_t ret;  	entry = iommu_range_alloc(dev, tbl, npages); -	if (unlikely(entry == bad_dma_address)) -		goto error; +	if (unlikely(entry == DMA_ERROR_CODE)) { +		printk(KERN_WARNING "Calgary: failed to allocate %u pages in " +		       "iommu %p\n", npages, tbl); +		return DMA_ERROR_CODE; +	}  	/* set the return dma address */  	ret = (entry << PAGE_SHIFT) | ((unsigned long)vaddr & ~PAGE_MASK); @@ -273,13 +277,7 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,  	/* put the TCEs in the HW table */  	tce_build(tbl, entry, npages, (unsigned long)vaddr & PAGE_MASK,  		  direction); -  	return ret; - -error: -	printk(KERN_WARNING "Calgary: failed to allocate %u pages in " -	       "iommu %p\n", npages, tbl); -	return bad_dma_address;  }  static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, @@ -290,8 +288,8 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,  	unsigned long flags;  	/* were we called with bad_dma_address? */ -	badend = bad_dma_address + (EMERGENCY_PAGES * PAGE_SIZE); -	if (unlikely((dma_addr >= bad_dma_address) && (dma_addr < badend))) { +	badend = DMA_ERROR_CODE + (EMERGENCY_PAGES * PAGE_SIZE); +	if (unlikely((dma_addr >= DMA_ERROR_CODE) && (dma_addr < badend))) {  		WARN(1, KERN_ERR "Calgary: driver tried unmapping bad DMA "  		       "address 0x%Lx\n", dma_addr);  		return; @@ -318,13 +316,15 @@ static inline struct iommu_table *find_iommu_table(struct device *dev)  	pdev = to_pci_dev(dev); +	/* search up the device tree for an iommu */  	pbus = pdev->bus; - -	/* is the device behind a bridge? Look for the root bus */ -	while (pbus->parent) +	do { +		tbl = pci_iommu(pbus); +		if (tbl && tbl->it_busno == pbus->number) +			break; +		tbl = NULL;  		pbus = pbus->parent; - -	tbl = pci_iommu(pbus); +	} while (pbus);  	BUG_ON(tbl && (tbl->it_busno != pbus->number)); @@ -373,7 +373,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,  		npages = iommu_num_pages(vaddr, s->length, PAGE_SIZE);  		entry = iommu_range_alloc(dev, tbl, npages); -		if (entry == bad_dma_address) { +		if (entry == DMA_ERROR_CODE) {  			/* makes sure unmap knows to stop */  			s->dma_length = 0;  			goto error; @@ -391,7 +391,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,  error:  	calgary_unmap_sg(dev, sg, nelems, dir, NULL);  	for_each_sg(sg, s, nelems, i) { -		sg->dma_address = bad_dma_address; +		sg->dma_address = DMA_ERROR_CODE;  		sg->dma_length = 0;  	}  	return 0; @@ -446,7 +446,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,  	/* set up tces to cover the allocated range */  	mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL); -	if (mapping == bad_dma_address) +	if (mapping == DMA_ERROR_CODE)  		goto free;  	*dma_handle = mapping;  	return ret; @@ -727,7 +727,7 @@ static void __init calgary_reserve_regions(struct pci_dev *dev)  	struct iommu_table *tbl = pci_iommu(dev->bus);  	/* reserve EMERGENCY_PAGES from bad_dma_address and up */ -	iommu_range_reserve(tbl, bad_dma_address, EMERGENCY_PAGES); +	iommu_range_reserve(tbl, DMA_ERROR_CODE, EMERGENCY_PAGES);  	/* avoid the BIOS/VGA first 640KB-1MB region */  	/* for CalIOC2 - avoid the entire first MB */ @@ -1344,6 +1344,23 @@ static void __init get_tce_space_from_tar(void)  	return;  } +static int __init calgary_iommu_init(void) +{ +	int ret; + +	/* ok, we're trying to use Calgary - let's roll */ +	printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n"); + +	ret = calgary_init(); +	if (ret) { +		printk(KERN_ERR "PCI-DMA: Calgary init failed %d, " +		       "falling back to no_iommu\n", ret); +		return ret; +	} + +	return 0; +} +  void __init detect_calgary(void)  {  	int bus; @@ -1357,7 +1374,7 @@ void __init detect_calgary(void)  	 * if the user specified iommu=off or iommu=soft or we found  	 * another HW IOMMU already, bail out.  	 */ -	if (swiotlb || no_iommu || iommu_detected) +	if (no_iommu || iommu_detected)  		return;  	if (!use_calgary) @@ -1442,9 +1459,7 @@ void __init detect_calgary(void)  		printk(KERN_INFO "PCI-DMA: Calgary TCE table spec is %d\n",  		       specified_table_size); -		/* swiotlb for devices that aren't behind the Calgary. */ -		if (max_pfn > MAX_DMA32_PFN) -			swiotlb = 1; +		x86_init.iommu.iommu_init = calgary_iommu_init;  	}  	return; @@ -1457,35 +1472,6 @@ cleanup:  	}  } -int __init calgary_iommu_init(void) -{ -	int ret; - -	if (no_iommu || (swiotlb && !calgary_detected)) -		return -ENODEV; - -	if (!calgary_detected) -		return -ENODEV; - -	/* ok, we're trying to use Calgary - let's roll */ -	printk(KERN_INFO "PCI-DMA: Using Calgary IOMMU\n"); - -	ret = calgary_init(); -	if (ret) { -		printk(KERN_ERR "PCI-DMA: Calgary init failed %d, " -		       "falling back to no_iommu\n", ret); -		return ret; -	} - -	force_iommu = 1; -	bad_dma_address = 0x0; -	/* dma_ops is set to swiotlb or nommu */ -	if (!dma_ops) -		dma_ops = &nommu_dma_ops; - -	return 0; -} -  static int __init calgary_parse_options(char *p)  {  	unsigned int bridge; diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index a6e804d16c3..afcc58b69c7 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -11,10 +11,11 @@  #include <asm/gart.h>  #include <asm/calgary.h>  #include <asm/amd_iommu.h> +#include <asm/x86_init.h>  static int forbid_dac __read_mostly; -struct dma_map_ops *dma_ops; +struct dma_map_ops *dma_ops = &nommu_dma_ops;  EXPORT_SYMBOL(dma_ops);  static int iommu_sac_force __read_mostly; @@ -42,9 +43,6 @@ int iommu_detected __read_mostly = 0;   */  int iommu_pass_through __read_mostly; -dma_addr_t bad_dma_address __read_mostly = 0; -EXPORT_SYMBOL(bad_dma_address); -  /* Dummy device used for NULL arguments (normally ISA). */  struct device x86_dma_fallback_dev = {  	.init_name = "fallback device", @@ -126,20 +124,17 @@ void __init pci_iommu_alloc(void)  	/* free the range so iommu could get some range less than 4G */  	dma32_free_bootmem();  #endif +	if (pci_swiotlb_init()) +		return; -	/* -	 * The order of these functions is important for -	 * fall-back/fail-over reasons -	 */  	gart_iommu_hole_init();  	detect_calgary();  	detect_intel_iommu(); +	/* needs to be called after gart_iommu_hole_init */  	amd_iommu_detect(); - -	pci_swiotlb_init();  }  void *dma_generic_alloc_coherent(struct device *dev, size_t size, @@ -214,7 +209,7 @@ static __init int iommu_setup(char *p)  		if (!strncmp(p, "allowdac", 8))  			forbid_dac = 0;  		if (!strncmp(p, "nodac", 5)) -			forbid_dac = -1; +			forbid_dac = 1;  		if (!strncmp(p, "usedac", 6)) {  			forbid_dac = -1;  			return 1; @@ -289,25 +284,17 @@ static int __init pci_iommu_init(void)  #ifdef CONFIG_PCI  	dma_debug_add_bus(&pci_bus_type);  #endif +	x86_init.iommu.iommu_init(); -	calgary_iommu_init(); - -	intel_iommu_init(); +	if (swiotlb) { +		printk(KERN_INFO "PCI-DMA: " +		       "Using software bounce buffering for IO (SWIOTLB)\n"); +		swiotlb_print_info(); +	} else +		swiotlb_free(); -	amd_iommu_init(); - -	gart_iommu_init(); - -	no_iommu_init();  	return 0;  } - -void pci_iommu_shutdown(void) -{ -	gart_iommu_shutdown(); - -	amd_iommu_shutdown(); -}  /* Must execute after PCI subsystem */  rootfs_initcall(pci_iommu_init); diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index a7f1b64f86e..e6a0d402f17 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c @@ -39,6 +39,7 @@  #include <asm/swiotlb.h>  #include <asm/dma.h>  #include <asm/k8.h> +#include <asm/x86_init.h>  static unsigned long iommu_bus_base;	/* GART remapping area (physical) */  static unsigned long iommu_size;	/* size of remapping area bytes */ @@ -46,6 +47,8 @@ static unsigned long iommu_pages;	/* .. and in pages */  static u32 *iommu_gatt_base;		/* Remapping table */ +static dma_addr_t bad_dma_addr; +  /*   * If this is disabled the IOMMU will use an optimized flushing strategy   * of only flushing when an mapping is reused. With it true the GART is @@ -92,7 +95,7 @@ static unsigned long alloc_iommu(struct device *dev, int size,  	base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),  			   PAGE_SIZE) >> PAGE_SHIFT; -	boundary_size = ALIGN((unsigned long long)dma_get_seg_boundary(dev) + 1, +	boundary_size = ALIGN((u64)dma_get_seg_boundary(dev) + 1,  			      PAGE_SIZE) >> PAGE_SHIFT;  	spin_lock_irqsave(&iommu_bitmap_lock, flags); @@ -216,7 +219,7 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,  		if (panic_on_overflow)  			panic("dma_map_area overflow %lu bytes\n", size);  		iommu_full(dev, size, dir); -		return bad_dma_address; +		return bad_dma_addr;  	}  	for (i = 0; i < npages; i++) { @@ -294,7 +297,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,  	int i;  #ifdef CONFIG_IOMMU_DEBUG -	printk(KERN_DEBUG "dma_map_sg overflow\n"); +	pr_debug("dma_map_sg overflow\n");  #endif  	for_each_sg(sg, s, nents, i) { @@ -302,7 +305,7 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,  		if (nonforced_iommu(dev, addr, s->length)) {  			addr = dma_map_area(dev, addr, s->length, dir, 0); -			if (addr == bad_dma_address) { +			if (addr == bad_dma_addr) {  				if (i > 0)  					gart_unmap_sg(dev, sg, i, dir, NULL);  				nents = 0; @@ -389,12 +392,14 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,  	if (!dev)  		dev = &x86_dma_fallback_dev; -	out = 0; -	start = 0; -	start_sg = sgmap = sg; -	seg_size = 0; -	max_seg_size = dma_get_max_seg_size(dev); -	ps = NULL; /* shut up gcc */ +	out		= 0; +	start		= 0; +	start_sg	= sg; +	sgmap		= sg; +	seg_size	= 0; +	max_seg_size	= dma_get_max_seg_size(dev); +	ps		= NULL; /* shut up gcc */ +  	for_each_sg(sg, s, nents, i) {  		dma_addr_t addr = sg_phys(s); @@ -417,11 +422,12 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,  						 sgmap, pages, need) < 0)  					goto error;  				out++; -				seg_size = 0; -				sgmap = sg_next(sgmap); -				pages = 0; -				start = i; -				start_sg = s; + +				seg_size	= 0; +				sgmap		= sg_next(sgmap); +				pages		= 0; +				start		= i; +				start_sg	= s;  			}  		} @@ -455,7 +461,7 @@ error:  	iommu_full(dev, pages << PAGE_SHIFT, dir);  	for_each_sg(sg, s, nents, i) -		s->dma_address = bad_dma_address; +		s->dma_address = bad_dma_addr;  	return 0;  } @@ -479,7 +485,7 @@ gart_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_addr,  				     DMA_BIDIRECTIONAL, align_mask);  		flush_gart(); -		if (paddr != bad_dma_address) { +		if (paddr != bad_dma_addr) {  			*dma_addr = paddr;  			return page_address(page);  		} @@ -499,6 +505,11 @@ gart_free_coherent(struct device *dev, size_t size, void *vaddr,  	free_pages((unsigned long)vaddr, get_order(size));  } +static int gart_mapping_error(struct device *dev, dma_addr_t dma_addr) +{ +	return (dma_addr == bad_dma_addr); +} +  static int no_agp;  static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size) @@ -515,7 +526,7 @@ static __init unsigned long check_iommu_size(unsigned long aper, u64 aper_size)  	iommu_size -= round_up(a, PMD_PAGE_SIZE) - a;  	if (iommu_size < 64*1024*1024) { -		printk(KERN_WARNING +		pr_warning(  			"PCI-DMA: Warning: Small IOMMU %luMB."  			" Consider increasing the AGP aperture in BIOS\n",  				iommu_size >> 20); @@ -570,28 +581,32 @@ void set_up_gart_resume(u32 aper_order, u32 aper_alloc)  	aperture_alloc = aper_alloc;  } -static int gart_resume(struct sys_device *dev) +static void gart_fixup_northbridges(struct sys_device *dev)  { -	printk(KERN_INFO "PCI-DMA: Resuming GART IOMMU\n"); +	int i; -	if (fix_up_north_bridges) { -		int i; +	if (!fix_up_north_bridges) +		return; -		printk(KERN_INFO "PCI-DMA: Restoring GART aperture settings\n"); +	pr_info("PCI-DMA: Restoring GART aperture settings\n"); -		for (i = 0; i < num_k8_northbridges; i++) { -			struct pci_dev *dev = k8_northbridges[i]; +	for (i = 0; i < num_k8_northbridges; i++) { +		struct pci_dev *dev = k8_northbridges[i]; -			/* -			 * Don't enable translations just yet.  That is the next -			 * step.  Restore the pre-suspend aperture settings. -			 */ -			pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, -						aperture_order << 1); -			pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, -						aperture_alloc >> 25); -		} +		/* +		 * Don't enable translations just yet.  That is the next +		 * step.  Restore the pre-suspend aperture settings. +		 */ +		pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, aperture_order << 1); +		pci_write_config_dword(dev, AMD64_GARTAPERTUREBASE, aperture_alloc >> 25);  	} +} + +static int gart_resume(struct sys_device *dev) +{ +	pr_info("PCI-DMA: Resuming GART IOMMU\n"); + +	gart_fixup_northbridges(dev);  	enable_gart_translations(); @@ -604,15 +619,14 @@ static int gart_suspend(struct sys_device *dev, pm_message_t state)  }  static struct sysdev_class gart_sysdev_class = { -	.name = "gart", -	.suspend = gart_suspend, -	.resume = gart_resume, +	.name		= "gart", +	.suspend	= gart_suspend, +	.resume		= gart_resume,  };  static struct sys_device device_gart = { -	.id	= 0, -	.cls	= &gart_sysdev_class, +	.cls		= &gart_sysdev_class,  };  /* @@ -627,7 +641,8 @@ static __init int init_k8_gatt(struct agp_kern_info *info)  	void *gatt;  	int i, error; -	printk(KERN_INFO "PCI-DMA: Disabling AGP.\n"); +	pr_info("PCI-DMA: Disabling AGP.\n"); +  	aper_size = aper_base = info->aper_size = 0;  	dev = NULL;  	for (i = 0; i < num_k8_northbridges; i++) { @@ -645,6 +660,7 @@ static __init int init_k8_gatt(struct agp_kern_info *info)  	}  	if (!aper_base)  		goto nommu; +  	info->aper_base = aper_base;  	info->aper_size = aper_size >> 20; @@ -667,14 +683,14 @@ static __init int init_k8_gatt(struct agp_kern_info *info)  	flush_gart(); -	printk(KERN_INFO "PCI-DMA: aperture base @ %x size %u KB\n", +	pr_info("PCI-DMA: aperture base @ %x size %u KB\n",  	       aper_base, aper_size>>10);  	return 0;   nommu:  	/* Should not happen anymore */ -	printk(KERN_WARNING "PCI-DMA: More than 4GB of RAM and no IOMMU\n" +	pr_warning("PCI-DMA: More than 4GB of RAM and no IOMMU\n"  	       "falling back to iommu=soft.\n");  	return -1;  } @@ -686,14 +702,15 @@ static struct dma_map_ops gart_dma_ops = {  	.unmap_page			= gart_unmap_page,  	.alloc_coherent			= gart_alloc_coherent,  	.free_coherent			= gart_free_coherent, +	.mapping_error			= gart_mapping_error,  }; -void gart_iommu_shutdown(void) +static void gart_iommu_shutdown(void)  {  	struct pci_dev *dev;  	int i; -	if (no_agp && (dma_ops != &gart_dma_ops)) +	if (no_agp)  		return;  	for (i = 0; i < num_k8_northbridges; i++) { @@ -708,7 +725,7 @@ void gart_iommu_shutdown(void)  	}  } -void __init gart_iommu_init(void) +int __init gart_iommu_init(void)  {  	struct agp_kern_info info;  	unsigned long iommu_start; @@ -718,7 +735,7 @@ void __init gart_iommu_init(void)  	long i;  	if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) -		return; +		return 0;  #ifndef CONFIG_AGP_AMD64  	no_agp = 1; @@ -730,35 +747,28 @@ void __init gart_iommu_init(void)  		(agp_copy_info(agp_bridge, &info) < 0);  #endif -	if (swiotlb) -		return; - -	/* Did we detect a different HW IOMMU? */ -	if (iommu_detected && !gart_iommu_aperture) -		return; -  	if (no_iommu ||  	    (!force_iommu && max_pfn <= MAX_DMA32_PFN) ||  	    !gart_iommu_aperture ||  	    (no_agp && init_k8_gatt(&info) < 0)) {  		if (max_pfn > MAX_DMA32_PFN) { -			printk(KERN_WARNING "More than 4GB of memory " -			       "but GART IOMMU not available.\n"); -			printk(KERN_WARNING "falling back to iommu=soft.\n"); +			pr_warning("More than 4GB of memory but GART IOMMU not available.\n"); +			pr_warning("falling back to iommu=soft.\n");  		} -		return; +		return 0;  	}  	/* need to map that range */ -	aper_size = info.aper_size << 20; -	aper_base = info.aper_base; -	end_pfn = (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT); +	aper_size	= info.aper_size << 20; +	aper_base	= info.aper_base; +	end_pfn		= (aper_base>>PAGE_SHIFT) + (aper_size>>PAGE_SHIFT); +  	if (end_pfn > max_low_pfn_mapped) {  		start_pfn = (aper_base>>PAGE_SHIFT);  		init_memory_mapping(start_pfn<<PAGE_SHIFT, end_pfn<<PAGE_SHIFT);  	} -	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n"); +	pr_info("PCI-DMA: using GART IOMMU.\n");  	iommu_size = check_iommu_size(info.aper_base, aper_size);  	iommu_pages = iommu_size >> PAGE_SHIFT; @@ -773,8 +783,7 @@ void __init gart_iommu_init(void)  		ret = dma_debug_resize_entries(iommu_pages);  		if (ret) -			printk(KERN_DEBUG -			       "PCI-DMA: Cannot trace all the entries\n"); +			pr_debug("PCI-DMA: Cannot trace all the entries\n");  	}  #endif @@ -784,15 +793,14 @@ void __init gart_iommu_init(void)  	 */  	iommu_area_reserve(iommu_gart_bitmap, 0, EMERGENCY_PAGES); -	agp_memory_reserved = iommu_size; -	printk(KERN_INFO -	       "PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n", +	pr_info("PCI-DMA: Reserving %luMB of IOMMU area in the AGP aperture\n",  	       iommu_size >> 20); -	iommu_start = aper_size - iommu_size; -	iommu_bus_base = info.aper_base + iommu_start; -	bad_dma_address = iommu_bus_base; -	iommu_gatt_base = agp_gatt_table + (iommu_start>>PAGE_SHIFT); +	agp_memory_reserved	= iommu_size; +	iommu_start		= aper_size - iommu_size; +	iommu_bus_base		= info.aper_base + iommu_start; +	bad_dma_addr		= iommu_bus_base; +	iommu_gatt_base		= agp_gatt_table + (iommu_start>>PAGE_SHIFT);  	/*  	 * Unmap the IOMMU part of the GART. The alias of the page is @@ -814,7 +822,7 @@ void __init gart_iommu_init(void)  	 * the pages as Not-Present:  	 */  	wbinvd(); -	 +  	/*  	 * Now all caches are flushed and we can safely enable  	 * GART hardware.  Doing it early leaves the possibility @@ -838,6 +846,10 @@ void __init gart_iommu_init(void)  	flush_gart();  	dma_ops = &gart_dma_ops; +	x86_platform.iommu_shutdown = gart_iommu_shutdown; +	swiotlb = 0; + +	return 0;  }  void __init gart_parse_options(char *p) @@ -856,7 +868,7 @@ void __init gart_parse_options(char *p)  #endif  	if (isdigit(*p) && get_option(&p, &arg))  		iommu_size = arg; -	if (!strncmp(p, "fullflush", 8)) +	if (!strncmp(p, "fullflush", 9))  		iommu_fullflush = 1;  	if (!strncmp(p, "nofullflush", 11))  		iommu_fullflush = 0; diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c index a3933d4330c..22be12b60a8 100644 --- a/arch/x86/kernel/pci-nommu.c +++ b/arch/x86/kernel/pci-nommu.c @@ -33,7 +33,7 @@ static dma_addr_t nommu_map_page(struct device *dev, struct page *page,  	dma_addr_t bus = page_to_phys(page) + offset;  	WARN_ON(size == 0);  	if (!check_addr("map_single", dev, bus, size)) -		return bad_dma_address; +		return DMA_ERROR_CODE;  	flush_write_buffers();  	return bus;  } @@ -103,12 +103,3 @@ struct dma_map_ops nommu_dma_ops = {  	.sync_sg_for_device	= nommu_sync_sg_for_device,  	.is_phys		= 1,  }; - -void __init no_iommu_init(void) -{ -	if (dma_ops) -		return; - -	force_iommu = 0; /* no HW IOMMU */ -	dma_ops = &nommu_dma_ops; -} diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c index aaa6b7839f1..e3c0a66b9e7 100644 --- a/arch/x86/kernel/pci-swiotlb.c +++ b/arch/x86/kernel/pci-swiotlb.c @@ -42,18 +42,28 @@ static struct dma_map_ops swiotlb_dma_ops = {  	.dma_supported = NULL,  }; -void __init pci_swiotlb_init(void) +/* + * pci_swiotlb_init - initialize swiotlb if necessary + * + * This returns non-zero if we are forced to use swiotlb (by the boot + * option). + */ +int __init pci_swiotlb_init(void)  { +	int use_swiotlb = swiotlb | swiotlb_force; +  	/* don't initialize swiotlb if iommu=off (no_iommu=1) */  #ifdef CONFIG_X86_64 -	if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN)) +	if (!no_iommu && max_pfn > MAX_DMA32_PFN)  		swiotlb = 1;  #endif  	if (swiotlb_force)  		swiotlb = 1; +  	if (swiotlb) { -		printk(KERN_INFO "PCI-DMA: Using software bounce buffering for IO (SWIOTLB)\n"); -		swiotlb_init(); +		swiotlb_init(0);  		dma_ops = &swiotlb_dma_ops;  	} + +	return use_swiotlb;  } diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index f93078746e0..2b97fc5b124 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -23,7 +23,7 @@  # include <linux/ctype.h>  # include <linux/mc146818rtc.h>  #else -# include <asm/iommu.h> +# include <asm/x86_init.h>  #endif  /* @@ -622,7 +622,7 @@ void native_machine_shutdown(void)  #endif  #ifdef CONFIG_X86_64 -	pci_iommu_shutdown(); +	x86_platform.iommu_shutdown();  #endif  } diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 4449a4a2c2e..d11c5ff7c65 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -14,10 +14,13 @@  #include <asm/time.h>  #include <asm/irq.h>  #include <asm/tsc.h> +#include <asm/iommu.h>  void __cpuinit x86_init_noop(void) { }  void __init x86_init_uint_noop(unsigned int unused) { }  void __init x86_init_pgd_noop(pgd_t *unused) { } +int __init iommu_init_noop(void) { return 0; } +void iommu_shutdown_noop(void) { }  /*   * The platform setup functions are preset with the default functions @@ -62,6 +65,10 @@ struct x86_init_ops x86_init __initdata = {  		.tsc_pre_init		= x86_init_noop,  		.timer_init		= hpet_time_init,  	}, + +	.iommu = { +		.iommu_init		= iommu_init_noop, +	},  };  struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { @@ -72,4 +79,5 @@ struct x86_platform_ops x86_platform = {  	.calibrate_tsc			= native_calibrate_tsc,  	.get_wallclock			= mach_get_cmos_time,  	.set_wallclock			= mach_set_rtc_mmss, +	.iommu_shutdown			= iommu_shutdown_noop,  }; diff --git a/arch/x86/mm/testmmiotrace.c b/arch/x86/mm/testmmiotrace.c index 427fd1b56df..8565d944f7c 100644 --- a/arch/x86/mm/testmmiotrace.c +++ b/arch/x86/mm/testmmiotrace.c @@ -1,12 +1,13 @@  /*   * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>   */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/module.h>  #include <linux/io.h>  #include <linux/mmiotrace.h> -#define MODULE_NAME "testmmiotrace" -  static unsigned long mmio_address;  module_param(mmio_address, ulong, 0);  MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB " @@ -30,7 +31,7 @@ static unsigned v32(unsigned i)  static void do_write_test(void __iomem *p)  {  	unsigned int i; -	pr_info(MODULE_NAME ": write test.\n"); +	pr_info("write test.\n");  	mmiotrace_printk("Write test.\n");  	for (i = 0; i < 256; i++) @@ -47,7 +48,7 @@ static void do_read_test(void __iomem *p)  {  	unsigned int i;  	unsigned errs[3] = { 0 }; -	pr_info(MODULE_NAME ": read test.\n"); +	pr_info("read test.\n");  	mmiotrace_printk("Read test.\n");  	for (i = 0; i < 256; i++) @@ -68,7 +69,7 @@ static void do_read_test(void __iomem *p)  static void do_read_far_test(void __iomem *p)  { -	pr_info(MODULE_NAME ": read far test.\n"); +	pr_info("read far test.\n");  	mmiotrace_printk("Read far test.\n");  	ioread32(p + read_far); @@ -78,7 +79,7 @@ static void do_test(unsigned long size)  {  	void __iomem *p = ioremap_nocache(mmio_address, size);  	if (!p) { -		pr_err(MODULE_NAME ": could not ioremap, aborting.\n"); +		pr_err("could not ioremap, aborting.\n");  		return;  	}  	mmiotrace_printk("ioremap returned %p.\n", p); @@ -94,24 +95,22 @@ static int __init init(void)  	unsigned long size = (read_far) ? (8 << 20) : (16 << 10);  	if (mmio_address == 0) { -		pr_err(MODULE_NAME ": you have to use the module argument " -							"mmio_address.\n"); -		pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS" -				" YOU REALLY KNOW WHAT YOU ARE DOING!\n"); +		pr_err("you have to use the module argument mmio_address.\n"); +		pr_err("DO NOT LOAD THIS MODULE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!\n");  		return -ENXIO;  	} -	pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI " -		"address space, and writing 16 kB of rubbish in there.\n", -		 size >> 10, mmio_address); +	pr_warning("WARNING: mapping %lu kB @ 0x%08lx in PCI address space, " +		   "and writing 16 kB of rubbish in there.\n", +		   size >> 10, mmio_address);  	do_test(size); -	pr_info(MODULE_NAME ": All done.\n"); +	pr_info("All done.\n");  	return 0;  }  static void __exit cleanup(void)  { -	pr_debug(MODULE_NAME ": unloaded.\n"); +	pr_debug("unloaded.\n");  }  module_init(init); diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index dc99e26f8e5..1b392c9e853 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -177,9 +177,6 @@ static struct ata_port_operations pcmcia_8bit_port_ops = {  	.drain_fifo	= pcmcia_8bit_drain_fifo,  }; -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  struct pcmcia_config_check {  	unsigned long ctl_base; @@ -252,7 +249,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)  	struct ata_port *ap;  	struct ata_pcmcia_info *info;  	struct pcmcia_config_check *stk = NULL; -	int last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p; +	int is_kme = 0, ret = -ENOMEM, p;  	unsigned long io_base, ctl_base;  	void __iomem *io_addr, *ctl_addr;  	int n_ports = 1; @@ -271,7 +268,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)  	pdev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;  	pdev->io.IOAddrLines = 3;  	pdev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	pdev->irq.IRQInfo1 = IRQ_LEVEL_ID;  	pdev->conf.Attributes = CONF_ENABLE_IRQ;  	pdev->conf.IntType = INT_MEMORY_AND_IO; @@ -296,8 +292,13 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)  	}  	io_base = pdev->io.BasePort1;  	ctl_base = stk->ctl_base; -	CS_CHECK(RequestIRQ, pcmcia_request_irq(pdev, &pdev->irq)); -	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(pdev, &pdev->conf)); +	ret = pcmcia_request_irq(pdev, &pdev->irq); +	if (ret) +		goto failed; + +	ret = pcmcia_request_configuration(pdev, &pdev->conf); +	if (ret) +		goto failed;  	/* iomap */  	ret = -ENOMEM; @@ -351,8 +352,6 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)  	kfree(stk);  	return 0; -cs_failed: -	cs_error(pdev, last_fn, last_ret);  failed:  	kfree(stk);  	info->ndev = 0; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 965ece2c7e4..13bb69d2abb 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -735,6 +735,21 @@ diskstats(struct gendisk *disk, struct bio *bio, ulong duration, sector_t sector  	part_stat_unlock();  } +/* + * Ensure we don't create aliases in VI caches + */ +static inline void +killalias(struct bio *bio) +{ +	struct bio_vec *bv; +	int i; + +	if (bio_data_dir(bio) == READ) +		__bio_for_each_segment(bv, bio, i, 0) { +			flush_dcache_page(bv->bv_page); +		} +} +  void  aoecmd_ata_rsp(struct sk_buff *skb)  { @@ -853,8 +868,12 @@ aoecmd_ata_rsp(struct sk_buff *skb)  	if (buf && --buf->nframesout == 0 && buf->resid == 0) {  		diskstats(d->gd, buf->bio, jiffies - buf->stime, buf->sector); -		n = (buf->flags & BUFFL_FAIL) ? -EIO : 0; -		bio_endio(buf->bio, n); +		if (buf->flags & BUFFL_FAIL) +			bio_endio(buf->bio, -EIO); +		else { +			killalias(buf->bio); +			bio_endio(buf->bio, 0); +		}  		mempool_free(buf, d->bufpool);  	} diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index b0e569ba730..2acdc605cb4 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -867,11 +867,9 @@ static int bluecard_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;  	link->io.NumPorts1 = 8; -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = bluecard_interrupt; -	link->irq.Instance = info;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; @@ -905,22 +903,16 @@ static int bluecard_config(struct pcmcia_device *link)  			break;  	} -	if (i != 0) { -		cs_error(link, RequestIO, i); +	if (i != 0)  		goto failed; -	}  	i = pcmcia_request_irq(link, &link->irq); -	if (i != 0) { -		cs_error(link, RequestIRQ, i); +	if (i != 0)  		link->irq.AssignedIRQ = 0; -	}  	i = pcmcia_request_configuration(link, &link->conf); -	if (i != 0) { -		cs_error(link, RequestConfiguration, i); +	if (i != 0)  		goto failed; -	}  	if (bluecard_open(info) != 0)  		goto failed; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index d58e22b9f06..d814a2755cc 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -659,11 +659,9 @@ static int bt3c_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;  	link->io.NumPorts1 = 8; -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = bt3c_interrupt; -	link->irq.Instance = info;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; @@ -740,21 +738,16 @@ static int bt3c_config(struct pcmcia_device *link)  		goto found_port;  	BT_ERR("No usable port range found"); -	cs_error(link, RequestIO, -ENODEV);  	goto failed;  found_port:  	i = pcmcia_request_irq(link, &link->irq); -	if (i != 0) { -		cs_error(link, RequestIRQ, i); +	if (i != 0)  		link->irq.AssignedIRQ = 0; -	}  	i = pcmcia_request_configuration(link, &link->conf); -	if (i != 0) { -		cs_error(link, RequestConfiguration, i); +	if (i != 0)  		goto failed; -	}  	if (bt3c_open(info) != 0)  		goto failed; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index efd689a062e..d339464dc15 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -588,11 +588,9 @@ static int btuart_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;  	link->io.NumPorts1 = 8; -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = btuart_interrupt; -	link->irq.Instance = info;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; @@ -669,21 +667,16 @@ static int btuart_config(struct pcmcia_device *link)  		goto found_port;  	BT_ERR("No usable port range found"); -	cs_error(link, RequestIO, -ENODEV);  	goto failed;  found_port:  	i = pcmcia_request_irq(link, &link->irq); -	if (i != 0) { -		cs_error(link, RequestIRQ, i); +	if (i != 0)  		link->irq.AssignedIRQ = 0; -	}  	i = pcmcia_request_configuration(link, &link->conf); -	if (i != 0) { -		cs_error(link, RequestConfiguration, i); +	if (i != 0)  		goto failed; -	}  	if (btuart_open(info) != 0)  		goto failed; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index b881a9cd874..4f02a6f3c98 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -573,11 +573,9 @@ static int dtl1_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;  	link->io.NumPorts1 = 8; -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = dtl1_interrupt; -	link->irq.Instance = info;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; @@ -622,16 +620,12 @@ static int dtl1_config(struct pcmcia_device *link)  		goto failed;  	i = pcmcia_request_irq(link, &link->irq); -	if (i != 0) { -		cs_error(link, RequestIRQ, i); +	if (i != 0)  		link->irq.AssignedIRQ = 0; -	}  	i = pcmcia_request_configuration(link, &link->conf); -	if (i != 0) { -		cs_error(link, RequestConfiguration, i); +	if (i != 0)  		goto failed; -	}  	if (dtl1_open(info) != 0)  		goto failed; diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index ccb1fa89de2..2fb3a480f6b 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -56,9 +56,8 @@ config AGP_AMD  	  X on AMD Irongate, 761, and 762 chipsets.  config AGP_AMD64 -	tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU +	tristate "AMD Opteron/Athlon64 on-CPU GART support"  	depends on AGP && X86 -	default y if GART_IOMMU  	help  	  This option gives you AGP support for the GLX component of  	  X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index c250a31efa5..2db4c0a29b0 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -23,8 +23,6 @@    * All rights reserved. Licensed under dual BSD/GPL license.    */ -/* #define PCMCIA_DEBUG 6 */ -  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h> @@ -47,18 +45,17 @@  /* #define ATR_CSUM */ -#ifdef PCMCIA_DEBUG -#define reader_to_dev(x)	(&handle_to_dev(x->p_dev)) -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0600); -#define DEBUGP(n, rdr, x, args...) do { 				\ -	if (pc_debug >= (n))						\ -		dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, 	\ -			   __func__ , ## args);			\ +#define reader_to_dev(x)	(&x->p_dev->dev) + +/* n (debug level) is ignored */ +/* additional debug output may be enabled by re-compiling with + * CM4000_DEBUG set */ +/* #define CM4000_DEBUG */ +#define DEBUGP(n, rdr, x, args...) do { 		\ +		dev_dbg(reader_to_dev(rdr), "%s:" x, 	\ +			   __func__ , ## args);		\  	} while (0) -#else -#define DEBUGP(n, rdr, x, args...) -#endif +  static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";  #define	T_1SEC		(HZ) @@ -174,14 +171,13 @@ static unsigned char fi_di_table[10][14] = {  /* 9 */ {0x09,0x19,0x29,0x39,0x49,0x59,0x69,0x11,0x11,0x99,0xA9,0xB9,0xC9,0xD9}  }; -#ifndef PCMCIA_DEBUG +#ifndef CM4000_DEBUG  #define	xoutb	outb  #define	xinb	inb  #else  static inline void xoutb(unsigned char val, unsigned short port)  { -	if (pc_debug >= 7) -		printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); +	pr_debug("outb(val=%.2x,port=%.4x)\n", val, port);  	outb(val, port);  }  static inline unsigned char xinb(unsigned short port) @@ -189,8 +185,7 @@ static inline unsigned char xinb(unsigned short port)  	unsigned char val;  	val = inb(port); -	if (pc_debug >= 7) -		printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); +	pr_debug("%.2x=inb(%.4x)\n", val, port);  	return val;  } @@ -514,12 +509,10 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)  	for (i = 0; i < 4; i++) {  		xoutb(i, REG_BUF_ADDR(iobase));  		xoutb(dev->pts[i], REG_BUF_DATA(iobase));	/* buf data */ -#ifdef PCMCIA_DEBUG -		if (pc_debug >= 5) -			printk("0x%.2x ", dev->pts[i]); +#ifdef CM4000_DEBUG +		pr_debug("0x%.2x ", dev->pts[i]);  	} -	if (pc_debug >= 5) -		printk("\n"); +	pr_debug("\n");  #else  	}  #endif @@ -579,14 +572,13 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)  		pts_reply[i] = inb(REG_BUF_DATA(iobase));  	} -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG  	DEBUGP(2, dev, "PTSreply: ");  	for (i = 0; i < num_bytes_read; i++) { -		if (pc_debug >= 5) -			printk("0x%.2x ", pts_reply[i]); +		pr_debug("0x%.2x ", pts_reply[i]);  	} -	printk("\n"); -#endif	/* PCMCIA_DEBUG */ +	pr_debug("\n"); +#endif	/* CM4000_DEBUG */  	DEBUGP(5, dev, "Clear Tactive in Flags1\n");  	xoutb(0x20, REG_FLAGS1(iobase)); @@ -655,7 +647,7 @@ static void terminate_monitor(struct cm4000_dev *dev)  	DEBUGP(5, dev, "Delete timer\n");  	del_timer_sync(&dev->timer); -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG  	dev->monitor_running = 0;  #endif @@ -898,7 +890,7 @@ static void monitor_card(unsigned long p)  				DEBUGP(4, dev, "ATR checksum (0x%.2x, should "  				       "be zero) failed\n", dev->atr_csum);  			} -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG  			else if (test_bit(IS_BAD_LENGTH, &dev->flags)) {  				DEBUGP(4, dev, "ATR length error\n");  			} else { @@ -1415,7 +1407,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  	int size;  	int rc;  	void __user *argp = (void __user *)arg; -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG  	char *ioctl_names[CM_IOC_MAXNR + 1] = {  		[_IOC_NR(CM_IOCGSTATUS)] "CM_IOCGSTATUS",  		[_IOC_NR(CM_IOCGATR)] "CM_IOCGATR", @@ -1423,9 +1415,9 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		[_IOC_NR(CM_IOCSPTS)] "CM_IOCSPTS",  		[_IOC_NR(CM_IOSDBGLVL)] "CM4000_DBGLVL",  	}; -#endif  	DEBUGP(3, dev, "cmm_ioctl(device=%d.%d) %s\n", imajor(inode),  	       iminor(inode), ioctl_names[_IOC_NR(cmd)]); +#endif  	lock_kernel();  	rc = -ENODEV; @@ -1523,7 +1515,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		}  	case CM_IOCARDOFF: -#ifdef PCMCIA_DEBUG +#ifdef CM4000_DEBUG  		DEBUGP(4, dev, "... in CM_IOCARDOFF\n");  		if (dev->flags0 & 0x01) {  			DEBUGP(4, dev, "    Card inserted\n"); @@ -1625,18 +1617,9 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)  		}  		break; -#ifdef PCMCIA_DEBUG -	case CM_IOSDBGLVL:	/* set debug log level */ -		{ -			int old_pc_debug = 0; - -			old_pc_debug = pc_debug; -			if (copy_from_user(&pc_debug, argp, sizeof(int))) -				rc = -EFAULT; -			else if (old_pc_debug != pc_debug) -				DEBUGP(0, dev, "Changed debug log level " -				       "to %i\n", pc_debug); -		} +#ifdef CM4000_DEBUG +	case CM_IOSDBGLVL: +		rc = -ENOTTY;  		break;  #endif  	default: diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 4f0723b0797..a6a70e476be 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -17,8 +17,6 @@   * All rights reserved, Dual BSD/GPL Licensed.   */ -/* #define PCMCIA_DEBUG 6 */ -  #include <linux/kernel.h>  #include <linux/module.h>  #include <linux/slab.h> @@ -41,18 +39,16 @@  #include "cm4040_cs.h" -#ifdef PCMCIA_DEBUG -#define reader_to_dev(x)	(&handle_to_dev(x->p_dev)) -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0600); -#define DEBUGP(n, rdr, x, args...) do { 				\ -	if (pc_debug >= (n)) 						\ -		dev_printk(KERN_DEBUG, reader_to_dev(rdr), "%s:" x, 	\ -			   __func__ , ##args); 			\ +#define reader_to_dev(x)	(&x->p_dev->dev) + +/* n (debug level) is ignored */ +/* additional debug output may be enabled by re-compiling with + * CM4040_DEBUG set */ +/* #define CM4040_DEBUG */ +#define DEBUGP(n, rdr, x, args...) do { 		\ +		dev_dbg(reader_to_dev(rdr), "%s:" x, 	\ +			   __func__ , ## args);		\  	} while (0) -#else -#define DEBUGP(n, rdr, x, args...) -#endif  static char *version =  "OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte"; @@ -90,14 +86,13 @@ struct reader_dev {  static struct pcmcia_device *dev_table[CM_MAX_DEV]; -#ifndef PCMCIA_DEBUG +#ifndef CM4040_DEBUG  #define	xoutb	outb  #define	xinb	inb  #else  static inline void xoutb(unsigned char val, unsigned short port)  { -	if (pc_debug >= 7) -		printk(KERN_DEBUG "outb(val=%.2x,port=%.4x)\n", val, port); +	pr_debug("outb(val=%.2x,port=%.4x)\n", val, port);  	outb(val, port);  } @@ -106,8 +101,7 @@ static inline unsigned char xinb(unsigned short port)  	unsigned char val;  	val = inb(port); -	if (pc_debug >= 7) -		printk(KERN_DEBUG "%.2x=inb(%.4x)\n", val, port); +	pr_debug("%.2x=inb(%.4x)\n", val, port);  	return val;  }  #endif @@ -260,23 +254,22 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,  			return -EIO;  		}  	  	dev->r_buf[i] = xinb(iobase + REG_OFFSET_BULK_IN); -#ifdef PCMCIA_DEBUG -		if (pc_debug >= 6) -			printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); +#ifdef CM4040_DEBUG +		pr_debug("%lu:%2x ", i, dev->r_buf[i]);  	} -	printk("\n"); +	pr_debug("\n");  #else  	}  #endif  	bytes_to_read = 5 + le32_to_cpu(*(__le32 *)&dev->r_buf[1]); -	DEBUGP(6, dev, "BytesToRead=%lu\n", bytes_to_read); +	DEBUGP(6, dev, "BytesToRead=%zu\n", bytes_to_read);  	min_bytes_to_read = min(count, bytes_to_read + 5);  	min_bytes_to_read = min_t(size_t, min_bytes_to_read, READ_WRITE_BUFFER_SIZE); -	DEBUGP(6, dev, "Min=%lu\n", min_bytes_to_read); +	DEBUGP(6, dev, "Min=%zu\n", min_bytes_to_read);  	for (i = 0; i < (min_bytes_to_read-5); i++) {  		rc = wait_for_bulk_in_ready(dev); @@ -288,11 +281,10 @@ static ssize_t cm4040_read(struct file *filp, char __user *buf,  			return -EIO;  		}  		dev->r_buf[i+5] = xinb(iobase + REG_OFFSET_BULK_IN); -#ifdef PCMCIA_DEBUG -		if (pc_debug >= 6) -			printk(KERN_DEBUG "%lu:%2x ", i, dev->r_buf[i]); +#ifdef CM4040_DEBUG +		pr_debug("%lu:%2x ", i, dev->r_buf[i]);  	} -	printk("\n"); +	pr_debug("\n");  #else  	}  #endif @@ -547,7 +539,7 @@ static int cm4040_config_check(struct pcmcia_device *p_dev,  	p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK;  	rc = pcmcia_request_io(p_dev, &p_dev->io); -	dev_printk(KERN_INFO, &handle_to_dev(p_dev), +	dev_printk(KERN_INFO, &p_dev->dev,  		   "pcmcia_request_io returned 0x%x\n", rc);  	return rc;  } @@ -569,7 +561,7 @@ static int reader_config(struct pcmcia_device *link, int devno)  	fail_rc = pcmcia_request_configuration(link, &link->conf);  	if (fail_rc != 0) { -		dev_printk(KERN_INFO, &handle_to_dev(link), +		dev_printk(KERN_INFO, &link->dev,  			   "pcmcia_request_configuration failed 0x%x\n",  			   fail_rc);  		goto cs_release; diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 4c1820cad71..99cffdab105 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -1213,12 +1213,12 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,  irqreturn_t ipwireless_interrupt(int irq, void *dev_id)  { -	struct ipw_hardware *hw = dev_id; +	struct ipw_dev *ipw = dev_id; -	if (hw->hw_version == HW_VERSION_1) -		return ipwireless_handle_v1_interrupt(irq, hw); +	if (ipw->hardware->hw_version == HW_VERSION_1) +		return ipwireless_handle_v1_interrupt(irq, ipw->hardware);  	else -		return ipwireless_handle_v2_v3_interrupt(irq, hw); +		return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware);  }  static void flush_packets_to_hw(struct ipw_hardware *hw) diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index 5216fce0c62..dff24dae148 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -65,10 +65,7 @@ static void signalled_reboot_work(struct work_struct *work_reboot)  	struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,  			work_reboot);  	struct pcmcia_device *link = ipw->link; -	int ret = pcmcia_reset_card(link->socket); - -	if (ret != 0) -		cs_error(link, ResetCard, ret); +	pcmcia_reset_card(link->socket);  }  static void signalled_reboot_callback(void *callback_data) @@ -79,208 +76,127 @@ static void signalled_reboot_callback(void *callback_data)  	schedule_work(&ipw->work_reboot);  } -static int config_ipwireless(struct ipw_dev *ipw) +static int ipwireless_probe(struct pcmcia_device *p_dev, +			    cistpl_cftable_entry_t *cfg, +			    cistpl_cftable_entry_t *dflt, +			    unsigned int vcc, +			    void *priv_data)  { -	struct pcmcia_device *link = ipw->link; -	int ret; -	tuple_t tuple; -	unsigned short buf[64]; -	cisparse_t parse; -	unsigned short cor_value; +	struct ipw_dev *ipw = priv_data; +	struct resource *io_resource;  	memreq_t memreq_attr_memory;  	memreq_t memreq_common_memory; +	int ret; -	ipw->is_v2_card = 0; - -	tuple.Attributes = 0; -	tuple.TupleData = (cisdata_t *) buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	tuple.DesiredTuple = RETURN_FIRST_TUPLE; - -	ret = pcmcia_get_first_tuple(link, &tuple); - -	while (ret == 0) { -		ret = pcmcia_get_tuple_data(link, &tuple); - -		if (ret != 0) { -			cs_error(link, GetTupleData, ret); -			goto exit0; -		} -		ret = pcmcia_get_next_tuple(link, &tuple); -	} - -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - -	ret = pcmcia_get_first_tuple(link, &tuple); - -	if (ret != 0) { -		cs_error(link, GetFirstTuple, ret); -		goto exit0; -	} - -	ret = pcmcia_get_tuple_data(link, &tuple); - -	if (ret != 0) { -		cs_error(link, GetTupleData, ret); -		goto exit0; -	} - -	ret = pcmcia_parse_tuple(&tuple, &parse); - -	if (ret != 0) { -		cs_error(link, ParseTuple, ret); -		goto exit0; -	} - -	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -	link->io.BasePort1 = parse.cftable_entry.io.win[0].base; -	link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; -	link->io.IOAddrLines = 16; - -	link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; +	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +	p_dev->io.BasePort1 = cfg->io.win[0].base; +	p_dev->io.NumPorts1 = cfg->io.win[0].len; +	p_dev->io.IOAddrLines = 16;  	/* 0x40 causes it to generate level mode interrupts. */  	/* 0x04 enables IREQ pin. */ -	cor_value = parse.cftable_entry.index | 0x44; -	link->conf.ConfigIndex = cor_value; +	p_dev->conf.ConfigIndex = cfg->index | 0x44; +	ret = pcmcia_request_io(p_dev, &p_dev->io); +	if (ret) +		return ret; -	/* IRQ and I/O settings */ -	tuple.DesiredTuple = CISTPL_CONFIG; +	io_resource = request_region(p_dev->io.BasePort1, p_dev->io.NumPorts1, +				IPWIRELESS_PCCARD_NAME); -	ret = pcmcia_get_first_tuple(link, &tuple); +	if (cfg->mem.nwin == 0) +		return 0; -	if (ret != 0) { -		cs_error(link, GetFirstTuple, ret); -		goto exit0; -	} +	ipw->request_common_memory.Attributes = +		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; +	ipw->request_common_memory.Base = cfg->mem.win[0].host_addr; +	ipw->request_common_memory.Size = cfg->mem.win[0].len; +	if (ipw->request_common_memory.Size < 0x1000) +		ipw->request_common_memory.Size = 0x1000; +	ipw->request_common_memory.AccessSpeed = 0; -	ret = pcmcia_get_tuple_data(link, &tuple); - -	if (ret != 0) { -		cs_error(link, GetTupleData, ret); -		goto exit0; -	} +	ret = pcmcia_request_window(p_dev, &ipw->request_common_memory, +				&ipw->handle_common_memory); -	ret = pcmcia_parse_tuple(&tuple, &parse); +	if (ret != 0) +		goto exit1; -	if (ret != 0) { -		cs_error(link, GetTupleData, ret); -		goto exit0; -	} -	link->conf.Attributes = CONF_ENABLE_IRQ; -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; -	link->conf.IntType = INT_MEMORY_AND_IO; +	memreq_common_memory.CardOffset = cfg->mem.win[0].card_addr; +	memreq_common_memory.Page = 0; -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.Handler = ipwireless_interrupt; -	link->irq.Instance = ipw->hardware; +	ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory, +				&memreq_common_memory); -	ret = pcmcia_request_io(link, &link->io); +	if (ret != 0) +		goto exit2; -	if (ret != 0) { -		cs_error(link, RequestIO, ret); -		goto exit0; -	} +	ipw->is_v2_card = cfg->mem.win[0].len == 0x100; -	request_region(link->io.BasePort1, link->io.NumPorts1, +	ipw->common_memory = ioremap(ipw->request_common_memory.Base, +				ipw->request_common_memory.Size); +	request_mem_region(ipw->request_common_memory.Base, +			ipw->request_common_memory.Size,  			IPWIRELESS_PCCARD_NAME); -	/* memory settings */ - -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - -	ret = pcmcia_get_first_tuple(link, &tuple); - -	if (ret != 0) { -		cs_error(link, GetFirstTuple, ret); -		goto exit1; -	} - -	ret = pcmcia_get_tuple_data(link, &tuple); +	ipw->request_attr_memory.Attributes = +		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; +	ipw->request_attr_memory.Base = 0; +	ipw->request_attr_memory.Size = 0;	/* this used to be 0x1000 */ +	ipw->request_attr_memory.AccessSpeed = 0; -	if (ret != 0) { -		cs_error(link, GetTupleData, ret); -		goto exit1; -	} - -	ret = pcmcia_parse_tuple(&tuple, &parse); - -	if (ret != 0) { -		cs_error(link, ParseTuple, ret); -		goto exit1; -	} - -	if (parse.cftable_entry.mem.nwin > 0) { -		ipw->request_common_memory.Attributes = -			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; -		ipw->request_common_memory.Base = -			parse.cftable_entry.mem.win[0].host_addr; -		ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; -		if (ipw->request_common_memory.Size < 0x1000) -			ipw->request_common_memory.Size = 0x1000; -		ipw->request_common_memory.AccessSpeed = 0; +	ret = pcmcia_request_window(p_dev, &ipw->request_attr_memory, +				&ipw->handle_attr_memory); -		ret = pcmcia_request_window(&link, &ipw->request_common_memory, -				&ipw->handle_common_memory); +	if (ret != 0) +		goto exit2; -		if (ret != 0) { -			cs_error(link, RequestWindow, ret); -			goto exit1; -		} +	memreq_attr_memory.CardOffset = 0; +	memreq_attr_memory.Page = 0; -		memreq_common_memory.CardOffset = -			parse.cftable_entry.mem.win[0].card_addr; -		memreq_common_memory.Page = 0; +	ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, +				&memreq_attr_memory); -		ret = pcmcia_map_mem_page(ipw->handle_common_memory, -				&memreq_common_memory); +	if (ret != 0) +		goto exit3; -		if (ret != 0) { -			cs_error(link, MapMemPage, ret); -			goto exit1; -		} +	ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, +				ipw->request_attr_memory.Size); +	request_mem_region(ipw->request_attr_memory.Base, +			ipw->request_attr_memory.Size, IPWIRELESS_PCCARD_NAME); -		ipw->is_v2_card = -			parse.cftable_entry.mem.win[0].len == 0x100; +	return 0; -		ipw->common_memory = ioremap(ipw->request_common_memory.Base, +exit3: +	pcmcia_release_window(p_dev, ipw->handle_attr_memory); +exit2: +	if (ipw->common_memory) { +		release_mem_region(ipw->request_common_memory.Base,  				ipw->request_common_memory.Size); -		request_mem_region(ipw->request_common_memory.Base, -				ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); - -		ipw->request_attr_memory.Attributes = -			WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; -		ipw->request_attr_memory.Base = 0; -		ipw->request_attr_memory.Size = 0;	/* this used to be 0x1000 */ -		ipw->request_attr_memory.AccessSpeed = 0; - -		ret = pcmcia_request_window(&link, &ipw->request_attr_memory, -				&ipw->handle_attr_memory); +		iounmap(ipw->common_memory); +		pcmcia_release_window(p_dev, ipw->handle_common_memory); +	} else +		pcmcia_release_window(p_dev, ipw->handle_common_memory); +exit1: +	release_resource(io_resource); +	pcmcia_disable_device(p_dev); +	return -1; +} -		if (ret != 0) { -			cs_error(link, RequestWindow, ret); -			goto exit2; -		} +static int config_ipwireless(struct ipw_dev *ipw) +{ +	struct pcmcia_device *link = ipw->link; +	int ret = 0; -		memreq_attr_memory.CardOffset = 0; -		memreq_attr_memory.Page = 0; +	ipw->is_v2_card = 0; -		ret = pcmcia_map_mem_page(ipw->handle_attr_memory, -				&memreq_attr_memory); +	ret = pcmcia_loop_config(link, ipwireless_probe, ipw); +	if (ret != 0) +		return ret; -		if (ret != 0) { -			cs_error(link, MapMemPage, ret); -			goto exit2; -		} +	link->conf.Attributes = CONF_ENABLE_IRQ; +	link->conf.IntType = INT_MEMORY_AND_IO; -		ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, -				ipw->request_attr_memory.Size); -		request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, -				IPWIRELESS_PCCARD_NAME); -	} +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; +	link->irq.Handler = ipwireless_interrupt;  	INIT_WORK(&ipw->work_reboot, signalled_reboot_work); @@ -291,10 +207,8 @@ static int config_ipwireless(struct ipw_dev *ipw)  	ret = pcmcia_request_irq(link, &link->irq); -	if (ret != 0) { -		cs_error(link, RequestIRQ, ret); -		goto exit3; -	} +	if (ret != 0) +		goto exit;  	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",  			ipw->is_v2_card ? "V2/V3" : "V1"); @@ -316,12 +230,12 @@ static int config_ipwireless(struct ipw_dev *ipw)  	ipw->network = ipwireless_network_create(ipw->hardware);  	if (!ipw->network) -		goto exit3; +		goto exit;  	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network,  			ipw->nodes);  	if (!ipw->tty) -		goto exit3; +		goto exit;  	ipwireless_init_hardware_v2_v3(ipw->hardware); @@ -331,35 +245,27 @@ static int config_ipwireless(struct ipw_dev *ipw)  	 */  	ret = pcmcia_request_configuration(link, &link->conf); -	if (ret != 0) { -		cs_error(link, RequestConfiguration, ret); -		goto exit4; -	} +	if (ret != 0) +		goto exit;  	link->dev_node = &ipw->nodes[0];  	return 0; -exit4: -	pcmcia_disable_device(link); -exit3: +exit:  	if (ipw->attr_memory) {  		release_mem_region(ipw->request_attr_memory.Base,  				ipw->request_attr_memory.Size);  		iounmap(ipw->attr_memory); -		pcmcia_release_window(ipw->handle_attr_memory); -		pcmcia_disable_device(link); +		pcmcia_release_window(link, ipw->handle_attr_memory);  	} -exit2:  	if (ipw->common_memory) {  		release_mem_region(ipw->request_common_memory.Base,  				ipw->request_common_memory.Size);  		iounmap(ipw->common_memory); -		pcmcia_release_window(ipw->handle_common_memory); +		pcmcia_release_window(link, ipw->handle_common_memory);  	} -exit1:  	pcmcia_disable_device(link); -exit0:  	return -1;  } @@ -378,9 +284,9 @@ static void release_ipwireless(struct ipw_dev *ipw)  		iounmap(ipw->attr_memory);  	}  	if (ipw->common_memory) -		pcmcia_release_window(ipw->handle_common_memory); +		pcmcia_release_window(ipw->link, ipw->handle_common_memory);  	if (ipw->attr_memory) -		pcmcia_release_window(ipw->handle_attr_memory); +		pcmcia_release_window(ipw->link, ipw->handle_attr_memory);  	/* Break the link with Card Services */  	pcmcia_disable_device(ipw->link); @@ -406,7 +312,6 @@ static int ipwireless_attach(struct pcmcia_device *link)  	ipw->link = link;  	link->priv = ipw; -	link->irq.Instance = ipw;  	/* Link this device into our device list. */  	link->dev_node = &ipw->nodes[0]; @@ -421,7 +326,6 @@ static int ipwireless_attach(struct pcmcia_device *link)  	ret = config_ipwireless(ipw);  	if (ret != 0) { -		cs_error(link, RegisterClient, ret);  		ipwireless_detach(link);  		return ret;  	} diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index caf6e4d1946..c31a0d913d3 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -554,7 +554,6 @@ static int mgslpc_probe(struct pcmcia_device *link)      /* Interrupt setup */      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -    link->irq.IRQInfo1   = IRQ_LEVEL_ID;      link->irq.Handler = NULL;      link->conf.Attributes = 0; @@ -572,69 +571,51 @@ static int mgslpc_probe(struct pcmcia_device *link)  /* Card has been inserted.   */ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) +static int mgslpc_ioprobe(struct pcmcia_device *p_dev, +			  cistpl_cftable_entry_t *cfg, +			  cistpl_cftable_entry_t *dflt, +			  unsigned int vcc, +			  void *priv_data) +{ +	if (cfg->io.nwin > 0) { +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(cfg->io.flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(cfg->io.flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = cfg->io.win[0].base; +		p_dev->io.NumPorts1 = cfg->io.win[0].len; +		return pcmcia_request_io(p_dev, &p_dev->io); +	} +	return -ENODEV; +}  static int mgslpc_config(struct pcmcia_device *link)  {      MGSLPC_INFO *info = link->priv; -    tuple_t tuple; -    cisparse_t parse; -    int last_fn, last_ret; -    u_char buf[64]; -    cistpl_cftable_entry_t dflt = { 0 }; -    cistpl_cftable_entry_t *cfg; +    int ret;      if (debug_level >= DEBUG_LEVEL_INFO)  	    printk("mgslpc_config(0x%p)\n", link); -    tuple.Attributes = 0; -    tuple.TupleData = buf; -    tuple.TupleDataMax = sizeof(buf); -    tuple.TupleOffset = 0; - -    /* get CIS configuration entry */ - -    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -    CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - -    cfg = &(parse.cftable_entry); -    CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); -    CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse)); - -    if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; -    if (cfg->index == 0) -	    goto cs_failed; - -    link->conf.ConfigIndex = cfg->index; -    link->conf.Attributes |= CONF_ENABLE_IRQ; - -    /* IO window settings */ -    link->io.NumPorts1 = 0; -    if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -	    cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -	    link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -	    if (!(io->flags & CISTPL_IO_8BIT)) -		    link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -	    if (!(io->flags & CISTPL_IO_16BIT)) -		    link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -	    link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -	    link->io.BasePort1 = io->win[0].base; -	    link->io.NumPorts1 = io->win[0].len; -	    CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); -    } +    ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL); +    if (ret != 0) +	    goto failed;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO;      link->conf.ConfigIndex = 8;      link->conf.Present = PRESENT_OPTION; -    link->irq.Attributes |= IRQ_HANDLE_PRESENT;      link->irq.Handler     = mgslpc_isr; -    link->irq.Instance    = info; -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      info->io_base = link->io.BasePort1;      info->irq_level = link->irq.AssignedIRQ; @@ -654,8 +635,7 @@ static int mgslpc_config(struct pcmcia_device *link)      printk("\n");      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret); +failed:      mgslpc_release((u_long)link);      return -ENODEV;  } diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 47c2d276345..f06bb37defb 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -31,7 +31,7 @@  enum tpm_const {  	TPM_MINOR = 224,	/* officially assigned */ -	TPM_BUFSIZE = 2048, +	TPM_BUFSIZE = 4096,  	TPM_NUM_DEVICES = 256,  }; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 0b73e4ec1ad..2405f17b29d 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -257,6 +257,10 @@ out:  	return size;  } +static int itpm; +module_param(itpm, bool, 0444); +MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); +  /*   * If interrupts are used (signaled by an irq set in the vendor structure)   * tpm.c can skip polling for the data to be available as the interrupt is @@ -293,7 +297,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)  		wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,  			      &chip->vendor.int_queue);  		status = tpm_tis_status(chip); -		if ((status & TPM_STS_DATA_EXPECT) == 0) { +		if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {  			rc = -EIO;  			goto out_err;  		} @@ -467,6 +471,10 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,  		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",  		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); +	if (itpm) +		dev_info(dev, "Intel iTPM workaround enabled\n"); + +  	/* Figure out the capabilities */  	intfcaps =  	    ioread32(chip->vendor.iobase + @@ -629,6 +637,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {  	{"", 0},		/* User Specified */  	{"", 0}			/* Terminator */  }; +MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);  static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev)  { diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 5711ce5353c..4baf3d7d0f8 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c @@ -144,13 +144,6 @@ static int lnw_irq_type(unsigned irq, unsigned type)  static void lnw_irq_unmask(unsigned irq)  { -	struct lnw_gpio *lnw = get_irq_chip_data(irq); -	u32 gpio = irq - lnw->irq_base; -	u8 reg = gpio / 32; -	void __iomem *gedr; - -	gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); -	writel(BIT(gpio % 32), gedr);  };  static void lnw_irq_mask(unsigned irq) @@ -183,13 +176,11 @@ static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)  		gedr_v = readl(gedr);  		if (!gedr_v)  			continue; -		for (gpio = reg*32; gpio < reg*32+32; gpio++) { -			gedr_v = readl(gedr); +		for (gpio = reg*32; gpio < reg*32+32; gpio++)  			if (gedr_v & BIT(gpio % 32)) {  				pr_debug("pin %d triggered\n", gpio);  				generic_handle_irq(lnw->irq_base + gpio);  			} -		}  		/* clear the edge detect status bit */  		writel(gedr_v, gedr);  	} diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index 063b933d864..dd6396384c2 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c @@ -60,15 +60,6 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");  MODULE_DESCRIPTION("PCMCIA ATA/IDE card driver");  MODULE_LICENSE("Dual MPL/GPL"); -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -#ifdef CONFIG_PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -#else -#define DEBUG(n, args...) -#endif -  /*====================================================================*/  typedef struct ide_info_t { @@ -98,7 +89,7 @@ static int ide_probe(struct pcmcia_device *link)  {      ide_info_t *info; -    DEBUG(0, "ide_attach()\n"); +    dev_dbg(&link->dev, "ide_attach()\n");      /* Create new ide device */      info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -112,7 +103,6 @@ static int ide_probe(struct pcmcia_device *link)      link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;      link->io.IOAddrLines = 3;      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO; @@ -134,7 +124,7 @@ static void ide_detach(struct pcmcia_device *link)      ide_hwif_t *hwif = info->host->ports[0];      unsigned long data_addr, ctl_addr; -    DEBUG(0, "ide_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "ide_detach(0x%p)\n", link);      data_addr = hwif->io_ports.data_addr;      ctl_addr  = hwif->io_ports.ctl_addr; @@ -217,9 +207,6 @@ out_release:  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  struct pcmcia_config_check {  	unsigned long ctl_base;  	int skip_vcc; @@ -282,11 +269,11 @@ static int ide_config(struct pcmcia_device *link)  {      ide_info_t *info = link->priv;      struct pcmcia_config_check *stk = NULL; -    int last_ret = 0, last_fn = 0, is_kme = 0; +    int ret = 0, is_kme = 0;      unsigned long io_base, ctl_base;      struct ide_host *host; -    DEBUG(0, "ide_config(0x%p)\n", link); +    dev_dbg(&link->dev, "ide_config(0x%p)\n", link);      is_kme = ((link->manf_id == MANFID_KME) &&  	      ((link->card_id == PRODID_KME_KXLC005_A) || @@ -306,8 +293,12 @@ static int ide_config(struct pcmcia_device *link)      io_base = link->io.BasePort1;      ctl_base = stk->ctl_base; -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      /* disable drive interrupts during IDE probe */      outb(0x02, ctl_base); @@ -342,8 +333,6 @@ err_mem:      printk(KERN_NOTICE "ide-cs: ide_config failed memory allocation\n");      goto failed; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      kfree(stk);      ide_release(link); @@ -363,7 +352,7 @@ static void ide_release(struct pcmcia_device *link)      ide_info_t *info = link->priv;      struct ide_host *host = info->host; -    DEBUG(0, "ide_release(0x%p)\n", link); +    dev_dbg(&link->dev, "ide_release(0x%p)\n", link);      if (info->ndev)  	/* FIXME: if this fails we need to queue the cleanup somehow diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index a537925f765..2bcf1ace27c 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -447,6 +447,27 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "N10"),  		},  	}, +	{ +		.ident = "Dell Vostro 1320", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"), +		}, +	}, +	{ +		.ident = "Dell Vostro 1520", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"), +		}, +	}, +	{ +		.ident = "Dell Vostro 1720", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), +		}, +	},  	{ }  }; diff --git a/drivers/isdn/hardware/avm/avm_cs.c b/drivers/isdn/hardware/avm/avm_cs.c index c72565520e4..5a6ae646a63 100644 --- a/drivers/isdn/hardware/avm/avm_cs.c +++ b/drivers/isdn/hardware/avm/avm_cs.c @@ -111,8 +111,6 @@ static int avmcs_probe(struct pcmcia_device *p_dev)      p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;      p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; -    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; -      /* General socket configuration */      p_dev->conf.Attributes = CONF_ENABLE_IRQ;      p_dev->conf.IntType = INT_MEMORY_AND_IO; @@ -198,7 +196,6 @@ static int avmcs_config(struct pcmcia_device *link)  	 */  	i = pcmcia_request_irq(link, &link->irq);  	if (i != 0) { -	    cs_error(link, RequestIRQ, i);  	    /* undo */  	    pcmcia_disable_device(link);  	    break; @@ -209,7 +206,6 @@ static int avmcs_config(struct pcmcia_device *link)  	  */  	i = pcmcia_request_configuration(link, &link->conf);  	if (i != 0) { -	    cs_error(link, RequestConfiguration, i);  	    pcmcia_disable_device(link);  	    break;  	} diff --git a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c index 23560c897ec..f9bdff39cf4 100644 --- a/drivers/isdn/hisax/avma1_cs.c +++ b/drivers/isdn/hisax/avma1_cs.c @@ -30,22 +30,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA car  MODULE_AUTHOR("Carsten Paeth");  MODULE_LICENSE("GPL"); -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -119,7 +103,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)  {      local_info_t *local; -    DEBUG(0, "avma1cs_attach()\n"); +    dev_dbg(&p_dev->dev, "avma1cs_attach()\n");      /* Allocate space for private device-specific data */      local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -139,8 +123,6 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)      p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE;      p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; -    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; -      /* General socket configuration */      p_dev->conf.Attributes = CONF_ENABLE_IRQ;      p_dev->conf.IntType = INT_MEMORY_AND_IO; @@ -161,7 +143,7 @@ static int avma1cs_probe(struct pcmcia_device *p_dev)  static void avma1cs_detach(struct pcmcia_device *link)  { -	DEBUG(0, "avma1cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "avma1cs_detach(0x%p)\n", link);  	avma1cs_release(link);  	kfree(link->priv);  } /* avma1cs_detach */ @@ -203,7 +185,7 @@ static int avma1cs_config(struct pcmcia_device *link)      dev = link->priv; -    DEBUG(0, "avma1cs_config(0x%p)\n", link); +    dev_dbg(&link->dev, "avma1cs_config(0x%p)\n", link);      devname[0] = 0;      if (link->prod_id[1]) @@ -218,7 +200,6 @@ static int avma1cs_config(struct pcmcia_device *link)  	 */  	i = pcmcia_request_irq(link, &link->irq);  	if (i != 0) { -	    cs_error(link, RequestIRQ, i);  	    /* undo */  	    pcmcia_disable_device(link);  	    break; @@ -229,7 +210,6 @@ static int avma1cs_config(struct pcmcia_device *link)  	 */  	i = pcmcia_request_configuration(link, &link->conf);  	if (i != 0) { -	    cs_error(link, RequestConfiguration, i);  	    pcmcia_disable_device(link);  	    break;  	} @@ -281,7 +261,7 @@ static void avma1cs_release(struct pcmcia_device *link)  {  	local_info_t *local = link->priv; -	DEBUG(0, "avma1cs_release(0x%p)\n", link); +	dev_dbg(&link->dev, "avma1cs_release(0x%p)\n", link);  	/* now unregister function with hisax */  	HiSax_closecard(local->node.minor); diff --git a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c index f4d0fe29bcf..a2f709f5397 100644 --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -57,23 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards");  MODULE_AUTHOR("Klaus Lichtenwalder");  MODULE_LICENSE("Dual MPL/GPL"); -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -142,7 +125,7 @@ static int elsa_cs_probe(struct pcmcia_device *link)  {      local_info_t *local; -    DEBUG(0, "elsa_cs_attach()\n"); +    dev_dbg(&link->dev, "elsa_cs_attach()\n");      /* Allocate space for private device-specific data */      local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -155,7 +138,6 @@ static int elsa_cs_probe(struct pcmcia_device *link)      /* Interrupt setup */      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID;      link->irq.Handler = NULL;      /* @@ -188,7 +170,7 @@ static void elsa_cs_detach(struct pcmcia_device *link)  {  	local_info_t *info = link->priv; -	DEBUG(0, "elsa_cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "elsa_cs_detach(0x%p)\n", link);  	info->busy = 1;  	elsa_cs_release(link); @@ -231,30 +213,25 @@ static int elsa_cs_configcheck(struct pcmcia_device *p_dev,  static int elsa_cs_config(struct pcmcia_device *link)  {      local_info_t *dev; -    int i, last_fn; +    int i;      IsdnCard_t icard; -    DEBUG(0, "elsa_config(0x%p)\n", link); +    dev_dbg(&link->dev, "elsa_config(0x%p)\n", link);      dev = link->priv;      i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL); -    if (i != 0) { -	last_fn = RequestIO; -	goto cs_failed; -    } +    if (i != 0) +	goto failed;      i = pcmcia_request_irq(link, &link->irq);      if (i != 0) {          link->irq.AssignedIRQ = 0; -	last_fn = RequestIRQ; -        goto cs_failed; +	goto failed;      }      i = pcmcia_request_configuration(link, &link->conf); -    if (i != 0) { -      last_fn = RequestConfiguration; -      goto cs_failed; -    } +    if (i != 0) +	goto failed;      /* At this point, the dev_node_t structure(s) should be         initialized and arranged in a linked list at link->dev. *//*  */ @@ -290,8 +267,7 @@ static int elsa_cs_config(struct pcmcia_device *link)      	((local_info_t*)link->priv)->cardnr = i;      return 0; -cs_failed: -    cs_error(link, last_fn, i); +failed:      elsa_cs_release(link);      return -ENODEV;  } /* elsa_cs_config */ @@ -308,7 +284,7 @@ static void elsa_cs_release(struct pcmcia_device *link)  {      local_info_t *local = link->priv; -    DEBUG(0, "elsa_cs_release(0x%p)\n", link); +    dev_dbg(&link->dev, "elsa_cs_release(0x%p)\n", link);      if (local) {      	if (local->cardnr >= 0) { diff --git a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c index 9a3c9f5e4fe..af5d393cc2d 100644 --- a/drivers/isdn/hisax/sedlbauer_cs.c +++ b/drivers/isdn/hisax/sedlbauer_cs.c @@ -57,24 +57,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards");  MODULE_AUTHOR("Marcus Niemann");  MODULE_LICENSE("Dual MPL/GPL"); -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);  -static char *version = -"sedlbauer_cs.c 1.1a 2001/01/28 15:04:04 (M.Niemann)"; -#else -#define DEBUG(n, args...) -#endif -  /*====================================================================*/ @@ -151,7 +133,7 @@ static int sedlbauer_probe(struct pcmcia_device *link)  {      local_info_t *local; -    DEBUG(0, "sedlbauer_attach()\n"); +    dev_dbg(&link->dev, "sedlbauer_attach()\n");      /* Allocate space for private device-specific data */      local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -163,7 +145,6 @@ static int sedlbauer_probe(struct pcmcia_device *link)      /* Interrupt setup */      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      link->irq.Handler = NULL;      /* @@ -198,7 +179,7 @@ static int sedlbauer_probe(struct pcmcia_device *link)  static void sedlbauer_detach(struct pcmcia_device *link)  { -	DEBUG(0, "sedlbauer_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);  	((local_info_t *)link->priv)->stop = 1;  	sedlbauer_release(link); @@ -214,9 +195,6 @@ static void sedlbauer_detach(struct pcmcia_device *link)      device available to the system.  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int sedlbauer_config_check(struct pcmcia_device *p_dev,  				  cistpl_cftable_entry_t *cfg,  				  cistpl_cftable_entry_t *dflt, @@ -293,11 +271,11 @@ static int sedlbauer_config_check(struct pcmcia_device *p_dev,  		req->Base = mem->win[0].host_addr;  		req->Size = mem->win[0].len;  		req->AccessSpeed = 0; -		if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) +		if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)  			return -ENODEV;  		map.Page = 0;  		map.CardOffset = mem->win[0].card_addr; -		if (pcmcia_map_mem_page(p_dev->win, &map) != 0) +		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)  			return -ENODEV;  	}  	return 0; @@ -309,10 +287,10 @@ static int sedlbauer_config(struct pcmcia_device *link)  {      local_info_t *dev = link->priv;      win_req_t *req; -    int last_fn, last_ret; +    int ret;      IsdnCard_t  icard; -    DEBUG(0, "sedlbauer_config(0x%p)\n", link); +    dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);      req = kzalloc(sizeof(win_req_t), GFP_KERNEL);      if (!req) @@ -330,8 +308,8 @@ static int sedlbauer_config(struct pcmcia_device *link)        these things without consulting the CIS, and most client drivers        will only use the CIS to fill in implementation-defined details.      */ -    last_ret = pcmcia_loop_config(link, sedlbauer_config_check, req); -    if (last_ret) +    ret = pcmcia_loop_config(link, sedlbauer_config_check, req); +    if (ret)  	    goto failed;      /* @@ -339,15 +317,20 @@ static int sedlbauer_config(struct pcmcia_device *link)         handler to the interrupt, unless the 'Handler' member of the         irq structure is initialized.      */ -    if (link->conf.Attributes & CONF_ENABLE_IRQ) -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +    if (link->conf.Attributes & CONF_ENABLE_IRQ) { +	    ret = pcmcia_request_irq(link, &link->irq); +	    if (ret) +		    goto failed; +    }      /*         This actually configures the PCMCIA socket -- setting up         the I/O windows and the interrupt mapping, and putting the         card and host interface into "Memory and IO" mode.      */ -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      /*        At this point, the dev_node_t structure(s) need to be @@ -380,19 +363,18 @@ static int sedlbauer_config(struct pcmcia_device *link)      icard.protocol = protocol;      icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; -    last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard); -    if (last_ret < 0) { -    	printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", -    		last_ret, link->io.BasePort1); +    ret = hisax_init_pcmcia(link,  +			    &(((local_info_t *)link->priv)->stop), &icard); +    if (ret < 0) { +	printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", +		ret, link->io.BasePort1);      	sedlbauer_release(link);  	return -ENODEV;      } else -    	((local_info_t*)link->priv)->cardnr = last_ret; +	((local_info_t *)link->priv)->cardnr = ret;      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      sedlbauer_release(link);      return -ENODEV; @@ -410,7 +392,7 @@ failed:  static void sedlbauer_release(struct pcmcia_device *link)  {      local_info_t *local = link->priv; -    DEBUG(0, "sedlbauer_release(0x%p)\n", link); +    dev_dbg(&link->dev, "sedlbauer_release(0x%p)\n", link);      if (local) {      	if (local->cardnr >= 0) { diff --git a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c index 623d111544d..ea705394ce2 100644 --- a/drivers/isdn/hisax/teles_cs.c +++ b/drivers/isdn/hisax/teles_cs.c @@ -38,23 +38,6 @@ MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards");  MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de");  MODULE_LICENSE("GPL"); -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -static char *version = -"teles_cs.c 2.10 2002/07/30 22:23:34 kkeil"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -133,7 +116,7 @@ static int teles_probe(struct pcmcia_device *link)  {      local_info_t *local; -    DEBUG(0, "teles_attach()\n"); +    dev_dbg(&link->dev, "teles_attach()\n");      /* Allocate space for private device-specific data */      local = kzalloc(sizeof(local_info_t), GFP_KERNEL); @@ -145,7 +128,6 @@ static int teles_probe(struct pcmcia_device *link)      /* Interrupt setup */      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID;      link->irq.Handler = NULL;      /* @@ -178,7 +160,7 @@ static void teles_detach(struct pcmcia_device *link)  {  	local_info_t *info = link->priv; -	DEBUG(0, "teles_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "teles_detach(0x%p)\n", link);  	info->busy = 1;  	teles_cs_release(link); @@ -221,30 +203,25 @@ static int teles_cs_configcheck(struct pcmcia_device *p_dev,  static int teles_cs_config(struct pcmcia_device *link)  {      local_info_t *dev; -    int i, last_fn; +    int i;      IsdnCard_t icard; -    DEBUG(0, "teles_config(0x%p)\n", link); +    dev_dbg(&link->dev, "teles_config(0x%p)\n", link);      dev = link->priv;      i = pcmcia_loop_config(link, teles_cs_configcheck, NULL); -    if (i != 0) { -	last_fn = RequestIO; +    if (i != 0)  	goto cs_failed; -    }      i = pcmcia_request_irq(link, &link->irq);      if (i != 0) {          link->irq.AssignedIRQ = 0; -	last_fn = RequestIRQ;          goto cs_failed;      }      i = pcmcia_request_configuration(link, &link->conf); -    if (i != 0) { -      last_fn = RequestConfiguration; +    if (i != 0)        goto cs_failed; -    }      /* At this point, the dev_node_t structure(s) should be         initialized and arranged in a linked list at link->dev. *//*  */ @@ -283,7 +260,6 @@ static int teles_cs_config(struct pcmcia_device *link)      return 0;  cs_failed: -    cs_error(link, last_fn, i);      teles_cs_release(link);      return -ENODEV;  } /* teles_cs_config */ @@ -300,7 +276,7 @@ static void teles_cs_release(struct pcmcia_device *link)  {      local_info_t *local = link->priv; -    DEBUG(0, "teles_cs_release(0x%p)\n", link); +    dev_dbg(&link->dev, "teles_cs_release(0x%p)\n", link);      if (local) {      	if (local->cardnr >= 0) { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a053423785c..e07ce2e033a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1650,11 +1650,12 @@ static void raid1d(mddev_t *mddev)  					       r1_bio->sector,  					       r1_bio->sectors);  				unfreeze_array(conf); -			} +			} else +				md_error(mddev, +					 conf->mirrors[r1_bio->read_disk].rdev);  			bio = r1_bio->bios[r1_bio->read_disk]; -			if ((disk=read_balance(conf, r1_bio)) == -1 || -			    disk == r1_bio->read_disk) { +			if ((disk=read_balance(conf, r1_bio)) == -1) {  				printk(KERN_ALERT "raid1: %s: unrecoverable I/O"  				       " read error for block %llu\n",  				       bdevname(bio->bi_bdev,b), diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index ddf639ed2fd..98082416aa5 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -31,6 +31,7 @@  #include <linux/wait.h>  #include <linux/slab.h>  #include <linux/poll.h> +#include <linux/semaphore.h>  #include <linux/module.h>  #include <linux/list.h>  #include <linux/freezer.h> diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 49b7885c270..7f27576ca04 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c @@ -29,7 +29,7 @@  /* Current settings - values are 2*2^(reg_val/4) microamps.  These are   * exported since they are used by multiple drivers.   */ -int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL] = { +int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1] = {  	2,  	2,  	3, diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index b00d6731905..9fb480bb0e0 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -760,6 +760,8 @@ static int pxamci_remove(struct platform_device *pdev)  	if (mmc) {  		struct pxamci_host *host = mmc_priv(mmc); +		mmc_remove_host(mmc); +  		if (host->pdata) {  			gpio_cd = host->pdata->gpio_card_detect;  			gpio_ro = host->pdata->gpio_card_ro; @@ -779,8 +781,6 @@ static int pxamci_remove(struct platform_device *pdev)  		if (host->pdata && host->pdata->exit)  			host->pdata->exit(&pdev->dev, mmc); -		mmc_remove_host(mmc); -  		pxamci_stop_clock(host);  		writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|  		       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index d600c2deff7..689d6a79ffc 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -118,11 +118,9 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)  		DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",  		      dev->offset, mrq.CardOffset);  		mrq.Page = 0; -		ret = pcmcia_map_mem_page(win, &mrq); -		if (ret != 0) { -			cs_error(dev->p_dev, MapMemPage, ret); +		ret = pcmcia_map_mem_page(dev->p_dev, win, &mrq); +		if (ret != 0)  			return NULL; -		}  		dev->offset = mrq.CardOffset;  	}  	return dev->win_base + (to & (dev->win_size-1)); @@ -327,8 +325,6 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)  	DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);  	ret = pcmcia_modify_configuration(link, &mod); -	if (ret != 0) -		cs_error(link, ModifyConfiguration, ret);  } @@ -348,107 +344,116 @@ static void pcmciamtd_release(struct pcmcia_device *link)  			iounmap(dev->win_base);  			dev->win_base = NULL;  		} -		pcmcia_release_window(link->win); +		pcmcia_release_window(link, link->win);  	}  	pcmcia_disable_device(link);  } -static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) +#ifdef CONFIG_MTD_DEBUG +static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev, +				tuple_t *tuple, +				void *priv_data)  { -	int rc; -	tuple_t tuple;  	cisparse_t parse; -	u_char buf[64]; -	tuple.Attributes = 0; -	tuple.TupleData = (cisdata_t *)buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; -	tuple.DesiredTuple = RETURN_FIRST_TUPLE; +	if (!pcmcia_parse_tuple(tuple, &parse)) { +		cistpl_format_t *t = &parse.format; +		(void)t; /* Shut up, gcc */ +		DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", +			t->type, t->edc, t->offset, t->length); +	} +	return -ENOSPC; +} -	rc = pcmcia_get_first_tuple(link, &tuple); -	while (rc == 0) { -		rc = pcmcia_get_tuple_data(link, &tuple); -		if (rc != 0) { -			cs_error(link, GetTupleData, rc); -			break; -		} -		rc = pcmcia_parse_tuple(&tuple, &parse); -		if (rc != 0) { -			cs_error(link, ParseTuple, rc); -			break; -		} +static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev, +				tuple_t *tuple, +				void *priv_data) +{ +	cisparse_t parse; +	int i; -		switch(tuple.TupleCode) { -		case  CISTPL_FORMAT: { -			cistpl_format_t *t = &parse.format; -			(void)t; /* Shut up, gcc */ -			DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u", -			      t->type, t->edc, t->offset, t->length); -			break; +	if (!pcmcia_parse_tuple(tuple, &parse)) { +		cistpl_jedec_t *t = &parse.jedec; +		for (i = 0; i < t->nid; i++) +			DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); +	} +	return -ENOSPC; +} +#endif -		} +static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev, +				tuple_t *tuple, +				void *priv_data) +{ +	struct pcmciamtd_dev *dev = priv_data; +	cisparse_t parse; +	cistpl_device_t *t = &parse.device; +	int i; -		case CISTPL_DEVICE: { -			cistpl_device_t *t = &parse.device; -			int i; -			DEBUG(2, "Common memory:"); -			dev->pcmcia_map.size = t->dev[0].size; -			for(i = 0; i < t->ndev; i++) { -				DEBUG(2, "Region %d, type = %u", i, t->dev[i].type); -				DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp); -				DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed); -				DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size); -			} -			break; -		} +	if (pcmcia_parse_tuple(tuple, &parse)) +		return -EINVAL; -		case CISTPL_VERS_1: { -			cistpl_vers_1_t *t = &parse.version_1; -			int i; -			if(t->ns) { -				dev->mtd_name[0] = '\0'; -				for(i = 0; i < t->ns; i++) { -					if(i) -						strcat(dev->mtd_name, " "); -					strcat(dev->mtd_name, t->str+t->ofs[i]); -				} -			} -			DEBUG(2, "Found name: %s", dev->mtd_name); -			break; -		} +	DEBUG(2, "Common memory:"); +	dev->pcmcia_map.size = t->dev[0].size; +	/* from here on: DEBUG only */ +	for (i = 0; i < t->ndev; i++) { +		DEBUG(2, "Region %d, type = %u", i, t->dev[i].type); +		DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp); +		DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed); +		DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size); +	} +	return 0; +} -		case CISTPL_JEDEC_C: { -			cistpl_jedec_t *t = &parse.jedec; -			int i; -			for(i = 0; i < t->nid; i++) { -				DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); -			} -			break; -		} +static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev, +				tuple_t *tuple, +				void *priv_data) +{ +	struct pcmciamtd_dev *dev = priv_data; +	cisparse_t parse; +	cistpl_device_geo_t *t = &parse.device_geo; +	int i; -		case CISTPL_DEVICE_GEO: { -			cistpl_device_geo_t *t = &parse.device_geo; -			int i; -			dev->pcmcia_map.bankwidth = t->geo[0].buswidth; -			for(i = 0; i < t->ngeo; i++) { -				DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth); -				DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block); -				DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block); -				DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block); -				DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition); -				DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave); -			} -			break; -		} +	if (pcmcia_parse_tuple(tuple, &parse)) +		return -EINVAL; -		default: -			DEBUG(2, "Unknown tuple code %d", tuple.TupleCode); -		} +	dev->pcmcia_map.bankwidth = t->geo[0].buswidth; +	/* from here on: DEBUG only */ +	for (i = 0; i < t->ngeo; i++) { +		DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth); +		DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block); +		DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block); +		DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block); +		DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition); +		DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave); +	} +	return 0; +} + + +static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) +{ +	int i; -		rc = pcmcia_get_next_tuple(link, &tuple); +	if (p_dev->prod_id[0]) { +		dev->mtd_name[0] = '\0'; +		for (i = 0; i < 4; i++) { +			if (i) +				strcat(dev->mtd_name, " "); +			if (p_dev->prod_id[i]) +				strcat(dev->mtd_name, p_dev->prod_id[i]); +		} +		DEBUG(2, "Found name: %s", dev->mtd_name);  	} + +#ifdef CONFIG_MTD_DEBUG +	pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL); +	pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL); +#endif +	pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev); +	pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev); +  	if(!dev->pcmcia_map.size)  		dev->pcmcia_map.size = MAX_PCMCIA_ADDR; @@ -481,16 +486,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link,   * MTD device available to the system.   */ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int pcmciamtd_config(struct pcmcia_device *link)  {  	struct pcmciamtd_dev *dev = link->priv;  	struct mtd_info *mtd = NULL;  	cs_status_t status;  	win_req_t req; -	int last_ret = 0, last_fn = 0;  	int ret;  	int i;  	static char *probes[] = { "jedec_probe", "cfi_probe" }; @@ -529,7 +530,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)  		int ret;  		DEBUG(2, "requesting window with size = %dKiB memspeed = %d",  		      req.Size >> 10, req.AccessSpeed); -		ret = pcmcia_request_window(&link, &req, &link->win); +		ret = pcmcia_request_window(link, &req, &link->win);  		DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);  		if(ret) {  			req.Size >>= 1; @@ -577,7 +578,6 @@ static int pcmciamtd_config(struct pcmcia_device *link)  	DEBUG(2, "Setting Configuration");  	ret = pcmcia_request_configuration(link, &link->conf);  	if (ret != 0) { -		cs_error(link, RequestConfiguration, ret);  		if (dev->win_base) {  			iounmap(dev->win_base);  			dev->win_base = NULL; @@ -652,8 +652,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)  	link->dev_node = &dev->node;  	return 0; - cs_failed: -	cs_error(link, last_fn, last_ret); + failed:  	err("CS Error, exiting");  	pcmciamtd_release(link);  	return -ENODEV; diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c index b58965a2b3a..17a27225cc9 100644 --- a/drivers/net/pcmcia/3c574_cs.c +++ b/drivers/net/pcmcia/3c574_cs.c @@ -118,14 +118,6 @@ INT_MODULE_PARM(full_duplex, 0);  /* Autodetect link polarity reversal? */  INT_MODULE_PARM(auto_polarity, 1); -#ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"3c574_cs.c 1.65ac1 2003/04/07 Donald Becker/David Hinds, becker@scyld.com.\n"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -278,7 +270,7 @@ static int tc574_probe(struct pcmcia_device *link)  	struct el3_private *lp;  	struct net_device *dev; -	DEBUG(0, "3c574_attach()\n"); +	dev_dbg(&link->dev, "3c574_attach()\n");  	/* Create the PC card device object. */  	dev = alloc_etherdev(sizeof(struct el3_private)); @@ -291,10 +283,8 @@ static int tc574_probe(struct pcmcia_device *link)  	spin_lock_init(&lp->window_lock);  	link->io.NumPorts1 = 32;  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = &el3_interrupt; -	link->irq.Instance = dev;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO;  	link->conf.ConfigIndex = 1; @@ -319,7 +309,7 @@ static void tc574_detach(struct pcmcia_device *link)  {  	struct net_device *dev = link->priv; -	DEBUG(0, "3c574_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "3c574_detach()\n");  	if (link->dev_node)  		unregister_netdev(dev); @@ -335,26 +325,23 @@ static void tc574_detach(struct pcmcia_device *link)  	ethernet device available to the system.  */ -#define CS_CHECK(fn, ret) \ -  do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};  static int tc574_config(struct pcmcia_device *link)  {  	struct net_device *dev = link->priv;  	struct el3_private *lp = netdev_priv(dev); -	tuple_t tuple; -	__le16 buf[32]; -	int last_fn, last_ret, i, j; +	int ret, i, j;  	unsigned int ioaddr;  	__be16 *phys_addr;  	char *cardname;  	__u32 config; +	u8 *buf; +	size_t len;  	phys_addr = (__be16 *)dev->dev_addr; -	DEBUG(0, "3c574_config(0x%p)\n", link); +	dev_dbg(&link->dev, "3c574_config()\n");  	link->io.IOAddrLines = 16;  	for (i = j = 0; j < 0x400; j += 0x20) { @@ -363,12 +350,16 @@ static int tc574_config(struct pcmcia_device *link)  		if (i == 0)  			break;  	} -	if (i != 0) { -		cs_error(link, RequestIO, i); +	if (i != 0) +		goto failed; + +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret) +		goto failed; + +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret)  		goto failed; -	} -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));  	dev->irq = link->irq.AssignedIRQ;  	dev->base_addr = link->io.BasePort1; @@ -378,16 +369,14 @@ static int tc574_config(struct pcmcia_device *link)  	/* The 3c574 normally uses an EEPROM for configuration info, including  	   the hardware address.  The future products may include a modem chip  	   and put the address in the CIS. */ -	tuple.Attributes = 0; -	tuple.TupleData = (cisdata_t *)buf; -	tuple.TupleDataMax = 64; -	tuple.TupleOffset = 0; -	tuple.DesiredTuple = 0x88; -	if (pcmcia_get_first_tuple(link, &tuple) == 0) { -		pcmcia_get_tuple_data(link, &tuple); + +	len = pcmcia_get_tuple(link, 0x88, &buf); +	if (buf && len >= 6) {  		for (i = 0; i < 3; i++) -			phys_addr[i] = htons(le16_to_cpu(buf[i])); +			phys_addr[i] = htons(le16_to_cpu(buf[i * 2])); +		kfree(buf);  	} else { +		kfree(buf); /* 0 < len < 6 */  		EL3WINDOW(0);  		for (i = 0; i < 3; i++)  			phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); @@ -435,7 +424,8 @@ static int tc574_config(struct pcmcia_device *link)  			mii_status = mdio_read(ioaddr, phy & 0x1f, 1);  			if (mii_status != 0xffff) {  				lp->phys = phy & 0x1f; -				DEBUG(0, "  MII transceiver at index %d, status %x.\n", +				dev_dbg(&link->dev, "  MII transceiver at " +					"index %d, status %x.\n",  					  phy, mii_status);  				if ((mii_status & 0x0040) == 0)  					mii_preamble_required = 1; @@ -457,7 +447,7 @@ static int tc574_config(struct pcmcia_device *link)  	}  	link->dev_node = &lp->node; -	SET_NETDEV_DEV(dev, &handle_to_dev(link)); +	SET_NETDEV_DEV(dev, &link->dev);  	if (register_netdev(dev) != 0) {  		printk(KERN_NOTICE "3c574_cs: register_netdev() failed\n"); @@ -478,8 +468,6 @@ static int tc574_config(struct pcmcia_device *link)  	return 0; -cs_failed: -	cs_error(link, last_fn, last_ret);  failed:  	tc574_release(link);  	return -ENODEV; @@ -738,7 +726,7 @@ static int el3_open(struct net_device *dev)  	lp->media.expires = jiffies + HZ;  	add_timer(&lp->media); -	DEBUG(2, "%s: opened, status %4.4x.\n", +	dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",  		  dev->name, inw(dev->base_addr + EL3_STATUS));  	return 0; @@ -772,7 +760,7 @@ static void pop_tx_status(struct net_device *dev)  		if (tx_status & 0x30)  			tc574_wait_for_completion(dev, TxReset);  		if (tx_status & 0x38) { -			DEBUG(1, "%s: transmit error: status 0x%02x\n", +			pr_debug("%s: transmit error: status 0x%02x\n",  				  dev->name, tx_status);  			outw(TxEnable, ioaddr + EL3_CMD);  			dev->stats.tx_aborted_errors++; @@ -788,7 +776,7 @@ static netdev_tx_t el3_start_xmit(struct sk_buff *skb,  	struct el3_private *lp = netdev_priv(dev);  	unsigned long flags; -	DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " +	pr_debug("%s: el3_start_xmit(length = %ld) called, "  		  "status %4.4x.\n", dev->name, (long)skb->len,  		  inw(ioaddr + EL3_STATUS)); @@ -827,7 +815,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)  		return IRQ_NONE;  	ioaddr = dev->base_addr; -	DEBUG(3, "%s: interrupt, status %4.4x.\n", +	pr_debug("%s: interrupt, status %4.4x.\n",  		  dev->name, inw(ioaddr + EL3_STATUS));  	spin_lock(&lp->window_lock); @@ -836,7 +824,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)  		   (IntLatch | RxComplete | RxEarly | StatsFull)) {  		if (!netif_device_present(dev) ||  			((status & 0xe000) != 0x2000)) { -			DEBUG(1, "%s: Interrupt from dead card\n", dev->name); +			pr_debug("%s: Interrupt from dead card\n", dev->name);  			break;  		} @@ -846,7 +834,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)  			work_budget = el3_rx(dev, work_budget);  		if (status & TxAvailable) { -			DEBUG(3, "  TX room bit was handled.\n"); +			pr_debug("  TX room bit was handled.\n");  			/* There's room in the FIFO for a full-sized packet. */  			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);  			netif_wake_queue(dev); @@ -886,7 +874,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)  		}  		if (--work_budget < 0) { -			DEBUG(0, "%s: Too much work in interrupt, " +			pr_debug("%s: Too much work in interrupt, "  				  "status %4.4x.\n", dev->name, status);  			/* Clear all interrupts */  			outw(AckIntr | 0xFF, ioaddr + EL3_CMD); @@ -896,7 +884,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)  		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);  	} -	DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", +	pr_debug("%s: exiting interrupt, status %4.4x.\n",  		  dev->name, inw(ioaddr + EL3_STATUS));  	spin_unlock(&lp->window_lock); @@ -1003,7 +991,7 @@ static void update_stats(struct net_device *dev)  	unsigned int ioaddr = dev->base_addr;  	u8 rx, tx, up; -	DEBUG(2, "%s: updating the statistics.\n", dev->name); +	pr_debug("%s: updating the statistics.\n", dev->name);  	if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */  		return; @@ -1039,7 +1027,7 @@ static int el3_rx(struct net_device *dev, int worklimit)  	unsigned int ioaddr = dev->base_addr;  	short rx_status; -	DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", +	pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",  		  dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus));  	while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) &&  			worklimit > 0) { @@ -1061,7 +1049,7 @@ static int el3_rx(struct net_device *dev, int worklimit)  			skb = dev_alloc_skb(pkt_len+5); -			DEBUG(3, "  Receiving packet size %d status %4.4x.\n", +			pr_debug("  Receiving packet size %d status %4.4x.\n",  				  pkt_len, rx_status);  			if (skb != NULL) {  				skb_reserve(skb, 2); @@ -1072,7 +1060,7 @@ static int el3_rx(struct net_device *dev, int worklimit)  				dev->stats.rx_packets++;  				dev->stats.rx_bytes += pkt_len;  			} else { -				DEBUG(1, "%s: couldn't allocate a sk_buff of" +				pr_debug("%s: couldn't allocate a sk_buff of"  					  " size %d.\n", dev->name, pkt_len);  				dev->stats.rx_dropped++;  			} @@ -1101,7 +1089,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  	struct mii_ioctl_data *data = if_mii(rq);  	int phy = lp->phys & 0x1f; -	DEBUG(2, "%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n", +	pr_debug("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n",  		  dev->name, rq->ifr_ifrn.ifrn_name, cmd,  		  data->phy_id, data->reg_num, data->val_in, data->val_out); @@ -1178,7 +1166,7 @@ static int el3_close(struct net_device *dev)  	struct el3_private *lp = netdev_priv(dev);  	struct pcmcia_device *link = lp->p_dev; -	DEBUG(2, "%s: shutting down ethercard.\n", dev->name); +	dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);  	if (pcmcia_dev_present(link)) {  		unsigned long flags; diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c index 569fb06793c..6f8d7e2e592 100644 --- a/drivers/net/pcmcia/3c589_cs.c +++ b/drivers/net/pcmcia/3c589_cs.c @@ -130,14 +130,6 @@ MODULE_LICENSE("GPL");  /* Special hook for setting if_port when module is loaded */  INT_MODULE_PARM(if_port, 0); -#ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -189,7 +181,7 @@ static int tc589_probe(struct pcmcia_device *link)      struct el3_private *lp;      struct net_device *dev; -    DEBUG(0, "3c589_attach()\n"); +    dev_dbg(&link->dev, "3c589_attach()\n");      /* Create new ethernet device */      dev = alloc_etherdev(sizeof(struct el3_private)); @@ -202,10 +194,8 @@ static int tc589_probe(struct pcmcia_device *link)      spin_lock_init(&lp->lock);      link->io.NumPorts1 = 16;      link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID; +    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;      link->irq.Handler = &el3_interrupt; -    link->irq.Instance = dev;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO;      link->conf.ConfigIndex = 1; @@ -231,7 +221,7 @@ static void tc589_detach(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    DEBUG(0, "3c589_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "3c589_detach\n");      if (link->dev_node)  	unregister_netdev(dev); @@ -249,29 +239,20 @@ static void tc589_detach(struct pcmcia_device *link)  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int tc589_config(struct pcmcia_device *link)  {      struct net_device *dev = link->priv;      struct el3_private *lp = netdev_priv(dev); -    tuple_t tuple; -    __le16 buf[32];      __be16 *phys_addr; -    int last_fn, last_ret, i, j, multi = 0, fifo; +    int ret, i, j, multi = 0, fifo;      unsigned int ioaddr;      char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; +    u8 *buf; +    size_t len; -    DEBUG(0, "3c589_config(0x%p)\n", link); +    dev_dbg(&link->dev, "3c589_config\n");      phys_addr = (__be16 *)dev->dev_addr; -    tuple.Attributes = 0; -    tuple.TupleData = (cisdata_t *)buf; -    tuple.TupleDataMax = sizeof(buf); -    tuple.TupleOffset = 0; -    tuple.Attributes = TUPLE_RETURN_COMMON; -      /* Is this a 3c562? */      if (link->manf_id != MANFID_3COM)  	    printk(KERN_INFO "3c589_cs: hmmm, is this really a " @@ -287,12 +268,16 @@ static int tc589_config(struct pcmcia_device *link)  	if (i == 0)  		break;      } -    if (i != 0) { -	cs_error(link, RequestIO, i); +    if (i != 0)  	goto failed; -    } -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); + +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; + +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      dev->irq = link->irq.AssignedIRQ;      dev->base_addr = link->io.BasePort1; @@ -301,12 +286,13 @@ static int tc589_config(struct pcmcia_device *link)      /* The 3c589 has an extra EEPROM for configuration info, including         the hardware address.  The 3c562 puts the address in the CIS. */ -    tuple.DesiredTuple = 0x88; -    if (pcmcia_get_first_tuple(link, &tuple) == 0) { -	pcmcia_get_tuple_data(link, &tuple); -	for (i = 0; i < 3; i++) -	    phys_addr[i] = htons(le16_to_cpu(buf[i])); +    len = pcmcia_get_tuple(link, 0x88, &buf); +    if (buf && len >= 6) { +	    for (i = 0; i < 3; i++) +		    phys_addr[i] = htons(le16_to_cpu(buf[i*2])); +	    kfree(buf);      } else { +	kfree(buf); /* 0 < len < 6 */  	for (i = 0; i < 3; i++)  	    phys_addr[i] = htons(read_eeprom(ioaddr, i));  	if (phys_addr[0] == htons(0x6060)) { @@ -328,7 +314,7 @@ static int tc589_config(struct pcmcia_device *link)  	printk(KERN_ERR "3c589_cs: invalid if_port requested\n");      link->dev_node = &lp->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if (register_netdev(dev) != 0) {  	printk(KERN_ERR "3c589_cs: register_netdev() failed\n"); @@ -347,8 +333,6 @@ static int tc589_config(struct pcmcia_device *link)  	   if_names[dev->if_port]);      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      tc589_release(link);      return -ENODEV; @@ -511,24 +495,8 @@ static void netdev_get_drvinfo(struct net_device *dev,  	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);  } -#ifdef PCMCIA_DEBUG -static u32 netdev_get_msglevel(struct net_device *dev) -{ -	return pc_debug; -} - -static void netdev_set_msglevel(struct net_device *dev, u32 level) -{ -	pc_debug = level; -} -#endif /* PCMCIA_DEBUG */ -  static const struct ethtool_ops netdev_ethtool_ops = {  	.get_drvinfo		= netdev_get_drvinfo, -#ifdef PCMCIA_DEBUG -	.get_msglevel		= netdev_get_msglevel, -	.set_msglevel		= netdev_set_msglevel, -#endif /* PCMCIA_DEBUG */  };  static int el3_config(struct net_device *dev, struct ifmap *map) @@ -563,7 +531,7 @@ static int el3_open(struct net_device *dev)      lp->media.expires = jiffies + HZ;      add_timer(&lp->media); -    DEBUG(1, "%s: opened, status %4.4x.\n", +    dev_dbg(&link->dev, "%s: opened, status %4.4x.\n",  	  dev->name, inw(dev->base_addr + EL3_STATUS));      return 0; @@ -596,7 +564,7 @@ static void pop_tx_status(struct net_device *dev)  	if (tx_status & 0x30)  	    tc589_wait_for_completion(dev, TxReset);  	if (tx_status & 0x38) { -	    DEBUG(1, "%s: transmit error: status 0x%02x\n", +	    pr_debug("%s: transmit error: status 0x%02x\n",  		  dev->name, tx_status);  	    outw(TxEnable, ioaddr + EL3_CMD);  	    dev->stats.tx_aborted_errors++; @@ -612,7 +580,7 @@ static netdev_tx_t el3_start_xmit(struct sk_buff *skb,      struct el3_private *priv = netdev_priv(dev);      unsigned long flags; -    DEBUG(3, "%s: el3_start_xmit(length = %ld) called, " +    pr_debug("%s: el3_start_xmit(length = %ld) called, "  	  "status %4.4x.\n", dev->name, (long)skb->len,  	  inw(ioaddr + EL3_STATUS)); @@ -654,14 +622,14 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)      ioaddr = dev->base_addr; -    DEBUG(3, "%s: interrupt, status %4.4x.\n", +    pr_debug("%s: interrupt, status %4.4x.\n",  	  dev->name, inw(ioaddr + EL3_STATUS));      spin_lock(&lp->lock);          while ((status = inw(ioaddr + EL3_STATUS)) &  	(IntLatch | RxComplete | StatsFull)) {  	if ((status & 0xe000) != 0x2000) { -	    DEBUG(1, "%s: interrupt from dead card\n", dev->name); +	    pr_debug("%s: interrupt from dead card\n", dev->name);  	    handled = 0;  	    break;  	} @@ -670,7 +638,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)  	    el3_rx(dev);  	if (status & TxAvailable) { -	    DEBUG(3, "    TX room bit was handled.\n"); +	    pr_debug("    TX room bit was handled.\n");  	    /* There's room in the FIFO for a full-sized packet. */  	    outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);  	    netif_wake_queue(dev); @@ -722,7 +690,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)      lp->last_irq = jiffies;      spin_unlock(&lp->lock);     -    DEBUG(3, "%s: exiting interrupt, status %4.4x.\n", +    pr_debug("%s: exiting interrupt, status %4.4x.\n",  	  dev->name, inw(ioaddr + EL3_STATUS));      return IRQ_RETVAL(handled);  } @@ -833,7 +801,7 @@ static void update_stats(struct net_device *dev)  {      unsigned int ioaddr = dev->base_addr; -    DEBUG(2, "%s: updating the statistics.\n", dev->name); +    pr_debug("%s: updating the statistics.\n", dev->name);      /* Turn off statistics updates while reading. */      outw(StatsDisable, ioaddr + EL3_CMD);      /* Switch to the stats window, and read everything. */ @@ -861,7 +829,7 @@ static int el3_rx(struct net_device *dev)      int worklimit = 32;      short rx_status; -    DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", +    pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",  	  dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));      while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&  		    worklimit > 0) { @@ -883,7 +851,7 @@ static int el3_rx(struct net_device *dev)  	    skb = dev_alloc_skb(pkt_len+5); -	    DEBUG(3, "    Receiving packet size %d status %4.4x.\n", +	    pr_debug("    Receiving packet size %d status %4.4x.\n",  		  pkt_len, rx_status);  	    if (skb != NULL) {  		skb_reserve(skb, 2); @@ -894,7 +862,7 @@ static int el3_rx(struct net_device *dev)  		dev->stats.rx_packets++;  		dev->stats.rx_bytes += pkt_len;  	    } else { -		DEBUG(1, "%s: couldn't allocate a sk_buff of" +		pr_debug("%s: couldn't allocate a sk_buff of"  		      " size %d.\n", dev->name, pkt_len);  		dev->stats.rx_dropped++;  	    } @@ -935,7 +903,7 @@ static int el3_close(struct net_device *dev)      struct pcmcia_device *link = lp->p_dev;      unsigned int ioaddr = dev->base_addr; -    DEBUG(1, "%s: shutting down ethercard.\n", dev->name); +    dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);      if (pcmcia_dev_present(link)) {  	/* Turn off statistics ASAP.  We update dev->stats below. */ diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index ca711f46814..81bafd57847 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -75,16 +75,6 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");  MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");  MODULE_LICENSE("GPL"); -#ifdef PCMCIA_DEBUG -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"axnet_cs.c 1.28 2002/06/29 06:27:37 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -167,7 +157,7 @@ static int axnet_probe(struct pcmcia_device *link)      struct net_device *dev;      struct ei_device *ei_local; -    DEBUG(0, "axnet_attach()\n"); +    dev_dbg(&link->dev, "axnet_attach()\n");      dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t));      if (!dev) @@ -180,7 +170,6 @@ static int axnet_probe(struct pcmcia_device *link)      info->p_dev = link;      link->priv = dev;      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO; @@ -205,7 +194,7 @@ static void axnet_detach(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    DEBUG(0, "axnet_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link);      if (link->dev_node)  	unregister_netdev(dev); @@ -272,9 +261,6 @@ static int get_prom(struct pcmcia_device *link)  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int try_io_port(struct pcmcia_device *link)  {      int j, ret; @@ -341,26 +327,29 @@ static int axnet_config(struct pcmcia_device *link)  {      struct net_device *dev = link->priv;      axnet_dev_t *info = PRIV(dev); -    int i, j, j2, last_ret, last_fn; +    int i, j, j2, ret; -    DEBUG(0, "axnet_config(0x%p)\n", link); +    dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);      /* don't trust the CIS on this; Linksys got it wrong */      link->conf.Present = 0x63; -    last_ret = pcmcia_loop_config(link, axnet_configcheck, NULL); -    if (last_ret != 0) { -	cs_error(link, RequestIO, last_ret); +    ret = pcmcia_loop_config(link, axnet_configcheck, NULL); +    if (ret != 0)  	goto failed; -    } -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed;      if (link->io.NumPorts2 == 8) {  	link->conf.Attributes |= CONF_ENABLE_SPKR;  	link->conf.Status = CCSR_AUDIO_ENA;      } -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed; +      dev->irq = link->irq.AssignedIRQ;      dev->base_addr = link->io.BasePort1; @@ -410,7 +399,7 @@ static int axnet_config(struct pcmcia_device *link)      info->phy_id = (i < 32) ? i : -1;      link->dev_node = &info->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if (register_netdev(dev) != 0) {  	printk(KERN_NOTICE "axnet_cs: register_netdev() failed\n"); @@ -426,14 +415,12 @@ static int axnet_config(struct pcmcia_device *link)  	   dev->base_addr, dev->irq,  	   dev->dev_addr);      if (info->phy_id != -1) { -	DEBUG(0, "  MII transceiver at index %d, status %x.\n", info->phy_id, j); +	dev_dbg(&link->dev, "  MII transceiver at index %d, status %x.\n", info->phy_id, j);      } else {  	printk(KERN_NOTICE "  No MII transceivers found!\n");      }      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      axnet_release(link);      return -ENODEV; @@ -543,7 +530,7 @@ static int axnet_open(struct net_device *dev)      struct pcmcia_device *link = info->p_dev;      unsigned int nic_base = dev->base_addr; -    DEBUG(2, "axnet_open('%s')\n", dev->name); +    dev_dbg(&link->dev, "axnet_open('%s')\n", dev->name);      if (!pcmcia_dev_present(link))  	return -ENODEV; @@ -572,7 +559,7 @@ static int axnet_close(struct net_device *dev)      axnet_dev_t *info = PRIV(dev);      struct pcmcia_device *link = info->p_dev; -    DEBUG(2, "axnet_close('%s')\n", dev->name); +    dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);      ax_close(dev);      free_irq(dev->irq, dev); @@ -741,10 +728,8 @@ static void block_input(struct net_device *dev, int count,      int xfer_count = count;      char *buf = skb->data; -#ifdef PCMCIA_DEBUG      if ((ei_debug > 4) && (count != 4)) -	printk(KERN_DEBUG "%s: [bi=%d]\n", dev->name, count+4); -#endif +	    pr_debug("%s: [bi=%d]\n", dev->name, count+4);      outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);      outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);      outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD); @@ -762,10 +747,7 @@ static void block_output(struct net_device *dev, int count,  {      unsigned int nic_base = dev->base_addr; -#ifdef PCMCIA_DEBUG -    if (ei_debug > 4) -	printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count); -#endif +    pr_debug("%s: [bo=%d]\n", dev->name, count);      /* Round the count up for word writes.  Do we need to do this?         What effect will an odd byte count have on the 8390? diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c index 7b5c77b7bd2..21d9c9d815d 100644 --- a/drivers/net/pcmcia/com20020_cs.c +++ b/drivers/net/pcmcia/com20020_cs.c @@ -53,11 +53,7 @@  #define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" -#ifdef PCMCIA_DEBUG - -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) +#ifdef DEBUG  static void regdump(struct net_device *dev)  { @@ -92,7 +88,6 @@ static void regdump(struct net_device *dev)  #else -#define DEBUG(n, args...) do { } while (0)  static inline void regdump(struct net_device *dev) { }  #endif @@ -144,7 +139,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)      struct net_device *dev;      struct arcnet_local *lp; -    DEBUG(0, "com20020_attach()\n"); +    dev_dbg(&p_dev->dev, "com20020_attach()\n");      /* Create new network device */      info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); @@ -169,11 +164,10 @@ static int com20020_probe(struct pcmcia_device *p_dev)      p_dev->io.NumPorts1 = 16;      p_dev->io.IOAddrLines = 16;      p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -    p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;      p_dev->conf.Attributes = CONF_ENABLE_IRQ;      p_dev->conf.IntType = INT_MEMORY_AND_IO; -    p_dev->irq.Instance = info->dev = dev; +    info->dev = dev;      p_dev->priv = info;      return com20020_config(p_dev); @@ -198,12 +192,12 @@ static void com20020_detach(struct pcmcia_device *link)      struct com20020_dev_t *info = link->priv;      struct net_device *dev = info->dev; -    DEBUG(1,"detach...\n"); +    dev_dbg(&link->dev, "detach...\n"); -    DEBUG(0, "com20020_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "com20020_detach\n");      if (link->dev_node) { -	DEBUG(1,"unregister...\n"); +	dev_dbg(&link->dev, "unregister...\n");  	unregister_netdev(dev); @@ -218,16 +212,16 @@ static void com20020_detach(struct pcmcia_device *link)      com20020_release(link);      /* Unlink device structure, free bits */ -    DEBUG(1,"unlinking...\n"); +    dev_dbg(&link->dev, "unlinking...\n");      if (link->priv)      {  	dev = info->dev;  	if (dev)  	{ -	    DEBUG(1,"kfree...\n"); +	    dev_dbg(&link->dev, "kfree...\n");  	    free_netdev(dev);  	} -	DEBUG(1,"kfree2...\n"); +	dev_dbg(&link->dev, "kfree2...\n");  	kfree(info);      } @@ -241,25 +235,22 @@ static void com20020_detach(struct pcmcia_device *link)  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int com20020_config(struct pcmcia_device *link)  {      struct arcnet_local *lp;      com20020_dev_t *info;      struct net_device *dev; -    int i, last_ret, last_fn; +    int i, ret;      int ioaddr;      info = link->priv;      dev = info->dev; -    DEBUG(1,"config...\n"); +    dev_dbg(&link->dev, "config...\n"); -    DEBUG(0, "com20020_config(0x%p)\n", link); +    dev_dbg(&link->dev, "com20020_config\n"); -    DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1); +    dev_dbg(&link->dev, "baseport1 is %Xh\n", link->io.BasePort1);      i = -ENODEV;      if (!link->io.BasePort1)      { @@ -276,26 +267,27 @@ static int com20020_config(struct pcmcia_device *link)      if (i != 0)      { -	DEBUG(1,"arcnet: requestIO failed totally!\n"); +	dev_dbg(&link->dev, "requestIO failed totally!\n");  	goto failed;      }      ioaddr = dev->base_addr = link->io.BasePort1; -    DEBUG(1,"arcnet: got ioaddr %Xh\n", ioaddr); +    dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); -    DEBUG(1,"arcnet: request IRQ %d (%Xh/%Xh)\n", -	   link->irq.AssignedIRQ, -	   link->irq.IRQInfo1, link->irq.IRQInfo2); +    dev_dbg(&link->dev, "request IRQ %d\n", +	    link->irq.AssignedIRQ);      i = pcmcia_request_irq(link, &link->irq);      if (i != 0)      { -	DEBUG(1,"arcnet: requestIRQ failed totally!\n"); +	dev_dbg(&link->dev, "requestIRQ failed totally!\n");  	goto failed;      }      dev->irq = link->irq.AssignedIRQ; -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      if (com20020_check(dev))      { @@ -308,26 +300,25 @@ static int com20020_config(struct pcmcia_device *link)      lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */      link->dev_node = &info->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      i = com20020_found(dev, 0);	/* calls register_netdev */      if (i != 0) { -	DEBUG(1,KERN_NOTICE "com20020_cs: com20020_found() failed\n"); +	dev_printk(KERN_NOTICE, &link->dev, +		"com20020_cs: com20020_found() failed\n");  	link->dev_node = NULL;  	goto failed;      }      strcpy(info->node.dev_name, dev->name); -    DEBUG(1,KERN_INFO "%s: port %#3lx, irq %d\n", +    dev_dbg(&link->dev,KERN_INFO "%s: port %#3lx, irq %d\n",             dev->name, dev->base_addr, dev->irq);      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed: -    DEBUG(1,"com20020_config failed...\n"); +    dev_dbg(&link->dev, "com20020_config failed...\n");      com20020_release(link);      return -ENODEV;  } /* com20020_config */ @@ -342,7 +333,7 @@ failed:  static void com20020_release(struct pcmcia_device *link)  { -	DEBUG(0, "com20020_release(0x%p)\n", link); +	dev_dbg(&link->dev, "com20020_release\n");  	pcmcia_disable_device(link);  } diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c index a6961215cd5..8ad8384fc1c 100644 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ b/drivers/net/pcmcia/fmvj18x_cs.c @@ -72,13 +72,6 @@ MODULE_LICENSE("GPL");  /* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */  INT_MODULE_PARM(sram_config, 0); -#ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/  /* @@ -245,7 +238,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)      local_info_t *lp;      struct net_device *dev; -    DEBUG(0, "fmvj18x_attach()\n"); +    dev_dbg(&link->dev, "fmvj18x_attach()\n");      /* Make up a FMVJ18x specific data structure */      dev = alloc_etherdev(sizeof(local_info_t)); @@ -262,10 +255,8 @@ static int fmvj18x_probe(struct pcmcia_device *link)      link->io.IOAddrLines = 5;      /* Interrupt setup */ -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID; +    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;      link->irq.Handler = fjn_interrupt; -    link->irq.Instance = dev;      /* General socket configuration */      link->conf.Attributes = CONF_ENABLE_IRQ; @@ -285,7 +276,7 @@ static void fmvj18x_detach(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    DEBUG(0, "fmvj18x_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "fmvj18x_detach\n");      if (link->dev_node)  	unregister_netdev(dev); @@ -297,9 +288,6 @@ static void fmvj18x_detach(struct pcmcia_device *link)  /*====================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int mfc_try_io_port(struct pcmcia_device *link)  {      int i, ret; @@ -341,33 +329,38 @@ static int ungermann_try_io_port(struct pcmcia_device *link)      return ret;	/* RequestIO failed */  } +static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, +			   cistpl_cftable_entry_t *cfg, +			   cistpl_cftable_entry_t *dflt, +			   unsigned int vcc, +			   void *priv_data) +{ +	return 0; /* strange, but that's what the code did already before... */ +} +  static int fmvj18x_config(struct pcmcia_device *link)  {      struct net_device *dev = link->priv;      local_info_t *lp = netdev_priv(dev); -    tuple_t tuple; -    cisparse_t parse; -    u_short buf[32]; -    int i, last_fn = 0, last_ret = 0, ret; +    int i, ret;      unsigned int ioaddr;      cardtype_t cardtype;      char *card_name = "unknown"; -    u_char *node_id; +    u8 *buf; +    size_t len; +    u_char buggybuf[32]; + +    dev_dbg(&link->dev, "fmvj18x_config\n"); -    DEBUG(0, "fmvj18x_config(0x%p)\n", link); +    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); +    kfree(buf); -    tuple.TupleData = (u_char *)buf; -    tuple.TupleDataMax = 64; -    tuple.TupleOffset = 0; -    tuple.DesiredTuple = CISTPL_FUNCE; -    tuple.TupleOffset = 0; -    if (pcmcia_get_first_tuple(link, &tuple) == 0) { +    if (len) {  	/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); -	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); -	CS_CHECK(ParseTuple, pcmcia_parse_tuple(&tuple, &parse)); -	link->conf.ConfigIndex = parse.cftable_entry.index; +	ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL); +	if (ret != 0) +		goto failed; +  	switch (link->manf_id) {  	case MANFID_TDK:  	    cardtype = TDK; @@ -433,17 +426,24 @@ static int fmvj18x_config(struct pcmcia_device *link)      if (link->io.NumPorts2 != 0) {      	link->irq.Attributes = -		IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; +		IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;  	ret = mfc_try_io_port(link); -	if (ret != 0) goto cs_failed; +	if (ret != 0) goto failed;      } else if (cardtype == UNGERMANN) {  	ret = ungermann_try_io_port(link); -	if (ret != 0) goto cs_failed; +	if (ret != 0) goto failed;      } else {  -	CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); +	    ret = pcmcia_request_io(link, &link->io); +	    if (ret) +		    goto failed;      } -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed; +      dev->irq = link->irq.AssignedIRQ;      dev->base_addr = link->io.BasePort1; @@ -474,21 +474,21 @@ static int fmvj18x_config(struct pcmcia_device *link)      case CONTEC:      case NEC:      case KME: -	tuple.DesiredTuple = CISTPL_FUNCE; -	tuple.TupleOffset = 0; -	CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); -	tuple.TupleOffset = 0; -	CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));  	if (cardtype == MBH10304) { -	    /* MBH10304's CIS_FUNCE is corrupted */ -	    node_id = &(tuple.TupleData[5]);  	    card_name = "FMV-J182"; -	} else { -	    while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) { -		CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); -		CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); + +	    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); +	    if (len < 11) { +		    kfree(buf); +		    goto failed;  	    } -	    node_id = &(tuple.TupleData[2]); +	    /* Read MACID from CIS */ +	    for (i = 5; i < 11; i++) +		    dev->dev_addr[i] = buf[i]; +	    kfree(buf); +	} else { +	    if (pcmcia_get_mac_from_cis(link, dev)) +		goto failed;  	    if( cardtype == TDK ) {  		card_name = "TDK LAK-CD021";  	    } else if( cardtype == LA501 ) { @@ -501,9 +501,6 @@ static int fmvj18x_config(struct pcmcia_device *link)  		card_name = "C-NET(PC)C";  	    }  	} -	/* Read MACID from CIS */ -	for (i = 0; i < 6; i++) -	    dev->dev_addr[i] = node_id[i];  	break;      case UNGERMANN:  	/* Read MACID from register */ @@ -513,12 +510,12 @@ static int fmvj18x_config(struct pcmcia_device *link)  	break;      case XXX10304:  	/* Read MACID from Buggy CIS */ -	if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) { +	if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {  	    printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");  	    goto failed;  	}  	for (i = 0 ; i < 6; i++) { -	    dev->dev_addr[i] = tuple.TupleData[i]; +	    dev->dev_addr[i] = buggybuf[i];  	}  	card_name = "FMV-J182";  	break; @@ -533,7 +530,7 @@ static int fmvj18x_config(struct pcmcia_device *link)      lp->cardtype = cardtype;      link->dev_node = &lp->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if (register_netdev(dev) != 0) {  	printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n"); @@ -551,9 +548,6 @@ static int fmvj18x_config(struct pcmcia_device *link)      return 0; -cs_failed: -    /* All Card Services errors end up here */ -    cs_error(link, last_fn, last_ret);  failed:      fmvj18x_release(link);      return -ENODEV; @@ -571,16 +565,14 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)      req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;      req.Base = 0; req.Size = 0;      req.AccessSpeed = 0; -    i = pcmcia_request_window(&link, &req, &link->win); -    if (i != 0) { -	cs_error(link, RequestWindow, i); +    i = pcmcia_request_window(link, &req, &link->win); +    if (i != 0)  	return -1; -    }      base = ioremap(req.Base, req.Size);      mem.Page = 0;      mem.CardOffset = 0; -    pcmcia_map_mem_page(link->win, &mem); +    pcmcia_map_mem_page(link, link->win, &mem);      /*       *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format @@ -605,9 +597,7 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)      }      iounmap(base); -    j = pcmcia_release_window(link->win); -    if (j != 0) -	cs_error(link, ReleaseWindow, j); +    j = pcmcia_release_window(link, link->win);      return (i != 0x200) ? 0 : -1;  } /* fmvj18x_get_hwinfo */ @@ -626,11 +616,9 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)      req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;      req.Base = 0; req.Size = 0;      req.AccessSpeed = 0; -    i = pcmcia_request_window(&link, &req, &link->win); -    if (i != 0) { -	cs_error(link, RequestWindow, i); +    i = pcmcia_request_window(link, &req, &link->win); +    if (i != 0)  	return -1; -    }      lp->base = ioremap(req.Base, req.Size);      if (lp->base == NULL) { @@ -640,11 +628,10 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)      mem.Page = 0;      mem.CardOffset = 0; -    i = pcmcia_map_mem_page(link->win, &mem); +    i = pcmcia_map_mem_page(link, link->win, &mem);      if (i != 0) {  	iounmap(lp->base);  	lp->base = NULL; -	cs_error(link, MapMemPage, i);  	return -1;      } @@ -671,15 +658,13 @@ static void fmvj18x_release(struct pcmcia_device *link)      u_char __iomem *tmp;      int j; -    DEBUG(0, "fmvj18x_release(0x%p)\n", link); +    dev_dbg(&link->dev, "fmvj18x_release\n");      if (lp->base != NULL) {  	tmp = lp->base;  	lp->base = NULL;    /* set NULL before iounmap */  	iounmap(tmp); -	j = pcmcia_release_window(link->win); -	if (j != 0) -	    cs_error(link, ReleaseWindow, j); +	j = pcmcia_release_window(link, link->win);      }      pcmcia_disable_device(link); @@ -788,8 +773,8 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)      outb(tx_stat, ioaddr + TX_STATUS);      outb(rx_stat, ioaddr + RX_STATUS); -    DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat); -    DEBUG(4, "               tx_status %02x.\n", tx_stat); +    pr_debug("%s: interrupt, rx_status %02x.\n", dev->name, rx_stat); +    pr_debug("               tx_status %02x.\n", tx_stat);      if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {  	/* there is packet(s) in rx buffer */ @@ -809,8 +794,8 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)  	}  	netif_wake_queue(dev);      } -    DEBUG(4, "%s: exiting interrupt,\n", dev->name); -    DEBUG(4, "    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat); +    pr_debug("%s: exiting interrupt,\n", dev->name); +    pr_debug("    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);      outb(D_TX_INTR, ioaddr + TX_INTR);      outb(D_RX_INTR, ioaddr + RX_INTR); @@ -882,7 +867,7 @@ static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,  	    return NETDEV_TX_BUSY;  	} -	DEBUG(4, "%s: Transmitting a packet of length %lu.\n", +	pr_debug("%s: Transmitting a packet of length %lu.\n",  	      dev->name, (unsigned long)skb->len);  	dev->stats.tx_bytes += skb->len; @@ -937,7 +922,7 @@ static void fjn_reset(struct net_device *dev)      unsigned int ioaddr = dev->base_addr;      int i; -    DEBUG(4, "fjn_reset(%s) called.\n",dev->name); +    pr_debug("fjn_reset(%s) called.\n",dev->name);      /* Reset controller */      if( sram_config == 0 )  @@ -1015,13 +1000,13 @@ static void fjn_rx(struct net_device *dev)      unsigned int ioaddr = dev->base_addr;      int boguscount = 10;	/* 5 -> 10: by agy 19940922 */ -    DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n", +    pr_debug("%s: in rx_packet(), rx_status %02x.\n",  	  dev->name, inb(ioaddr + RX_STATUS));      while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {  	u_short status = inw(ioaddr + DATAPORT); -	DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n", +	pr_debug("%s: Rxing packet mode %02x status %04x.\n",  	      dev->name, inb(ioaddr + RX_MODE), status);  #ifndef final_version  	if (status == 0) { @@ -1061,16 +1046,14 @@ static void fjn_rx(struct net_device *dev)  		 (pkt_len + 1) >> 1);  	    skb->protocol = eth_type_trans(skb, dev); -#ifdef PCMCIA_DEBUG -	    if (pc_debug > 5) { +	    {  		int i; -		printk(KERN_DEBUG "%s: Rxed packet of length %d: ", -		       dev->name, pkt_len); +		pr_debug("%s: Rxed packet of length %d: ", +			dev->name, pkt_len);  		for (i = 0; i < 14; i++) -		    printk(" %02x", skb->data[i]); -		printk(".\n"); +			pr_debug(" %02x", skb->data[i]); +		pr_debug(".\n");  	    } -#endif  	    netif_rx(skb);  	    dev->stats.rx_packets++; @@ -1094,7 +1077,7 @@ static void fjn_rx(struct net_device *dev)  	}  	if (i > 0) -	    DEBUG(5, "%s: Exint Rx packet with mode %02x after " +	    pr_debug("%s: Exint Rx packet with mode %02x after "  		  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);      }  */ @@ -1112,24 +1095,8 @@ static void netdev_get_drvinfo(struct net_device *dev,  	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);  } -#ifdef PCMCIA_DEBUG -static u32 netdev_get_msglevel(struct net_device *dev) -{ -	return pc_debug; -} - -static void netdev_set_msglevel(struct net_device *dev, u32 level) -{ -	pc_debug = level; -} -#endif /* PCMCIA_DEBUG */ -  static const struct ethtool_ops netdev_ethtool_ops = {  	.get_drvinfo		= netdev_get_drvinfo, -#ifdef PCMCIA_DEBUG -	.get_msglevel		= netdev_get_msglevel, -	.set_msglevel		= netdev_set_msglevel, -#endif /* PCMCIA_DEBUG */  };  static int fjn_config(struct net_device *dev, struct ifmap *map){ @@ -1141,7 +1108,7 @@ static int fjn_open(struct net_device *dev)      struct local_info_t *lp = netdev_priv(dev);      struct pcmcia_device *link = lp->p_dev; -    DEBUG(4, "fjn_open('%s').\n", dev->name); +    pr_debug("fjn_open('%s').\n", dev->name);      if (!pcmcia_dev_present(link))  	return -ENODEV; @@ -1167,7 +1134,7 @@ static int fjn_close(struct net_device *dev)      struct pcmcia_device *link = lp->p_dev;      unsigned int ioaddr = dev->base_addr; -    DEBUG(4, "fjn_close('%s').\n", dev->name); +    pr_debug("fjn_close('%s').\n", dev->name);      lp->open_time = 0;      netif_stop_queue(dev); diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c index 06618af1a46..37f4a6fdc3e 100644 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ b/drivers/net/pcmcia/ibmtr_cs.c @@ -69,17 +69,6 @@  #define PCMCIA  #include "../tokenring/ibmtr.c" -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"ibmtr_cs.c 1.10   1996/01/06 05:19:00 (Steve Kipisz)\n" -"           2.2.7  1999/05/03 12:00:00 (Mike Phillips)\n" -"           2.4.2  2001/30/28 Midnight (Burt Silverman)\n"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -130,6 +119,12 @@ static const struct ethtool_ops netdev_ethtool_ops = {  	.get_drvinfo		= netdev_get_drvinfo,  }; +static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) { +	ibmtr_dev_t *info = dev_id; +	struct net_device *dev = info->dev; +	return tok_interrupt(irq, dev); +}; +  /*======================================================================      ibmtr_attach() creates an "instance" of the driver, allocating @@ -143,7 +138,7 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)      ibmtr_dev_t *info;      struct net_device *dev; -    DEBUG(0, "ibmtr_attach()\n"); +    dev_dbg(&link->dev, "ibmtr_attach()\n");      /* Create new token-ring device */      info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -161,14 +156,13 @@ static int __devinit ibmtr_attach(struct pcmcia_device *link)      link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;      link->io.NumPorts1 = 4;      link->io.IOAddrLines = 16; -    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID; -    link->irq.Handler = &tok_interrupt; +    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; +    link->irq.Handler = ibmtr_interrupt;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO;      link->conf.Present = PRESENT_OPTION; -    link->irq.Instance = info->dev = dev; +    info->dev = dev;      SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); @@ -190,7 +184,7 @@ static void ibmtr_detach(struct pcmcia_device *link)      struct net_device *dev = info->dev;       struct tok_info *ti = netdev_priv(dev); -    DEBUG(0, "ibmtr_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "ibmtr_detach\n");      /*        * When the card removal interrupt hits tok_interrupt(),  @@ -217,9 +211,6 @@ static void ibmtr_detach(struct pcmcia_device *link)  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int __devinit ibmtr_config(struct pcmcia_device *link)  {      ibmtr_dev_t *info = link->priv; @@ -227,9 +218,9 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)      struct tok_info *ti = netdev_priv(dev);      win_req_t req;      memreq_t mem; -    int i, last_ret, last_fn; +    int i, ret; -    DEBUG(0, "ibmtr_config(0x%p)\n", link); +    dev_dbg(&link->dev, "ibmtr_config\n");      link->conf.ConfigIndex = 0x61; @@ -241,11 +232,15 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)      if (i != 0) {  	/* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */  	link->io.BasePort1 = 0xA24; -	CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); +	ret = pcmcia_request_io(link, &link->io); +	if (ret) +		goto failed;      }      dev->base_addr = link->io.BasePort1; -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed;      dev->irq = link->irq.AssignedIRQ;      ti->irq = link->irq.AssignedIRQ;      ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); @@ -256,11 +251,15 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)      req.Base = 0;       req.Size = 0x2000;      req.AccessSpeed = 250; -    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); +    ret = pcmcia_request_window(link, &req, &link->win); +    if (ret) +	    goto failed;      mem.CardOffset = mmiobase;      mem.Page = 0; -    CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); +    ret = pcmcia_map_mem_page(link, link->win, &mem); +    if (ret) +	    goto failed;      ti->mmio = ioremap(req.Base, req.Size);      /* Allocate the SRAM memory window */ @@ -269,17 +268,23 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)      req.Base = 0;      req.Size = sramsize * 1024;      req.AccessSpeed = 250; -    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &info->sram_win_handle)); +    ret = pcmcia_request_window(link, &req, &info->sram_win_handle); +    if (ret) +	    goto failed;      mem.CardOffset = srambase;      mem.Page = 0; -    CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem)); +    ret = pcmcia_map_mem_page(link, info->sram_win_handle, &mem); +    if (ret) +	    goto failed;      ti->sram_base = mem.CardOffset >> 12;      ti->sram_virt = ioremap(req.Base, req.Size);      ti->sram_phys = req.Base; -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      /*  Set up the Token-Ring Controller Configuration Register and          turn on the card.  Check the "Local Area Network Credit Card @@ -287,7 +292,7 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)      ibmtr_hw_setup(dev, mmiobase);      link->dev_node = &info->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      i = ibmtr_probe_card(dev);      if (i != 0) { @@ -305,8 +310,6 @@ static int __devinit ibmtr_config(struct pcmcia_device *link)  	   dev->dev_addr);      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      ibmtr_release(link);      return -ENODEV; @@ -325,12 +328,12 @@ static void ibmtr_release(struct pcmcia_device *link)  	ibmtr_dev_t *info = link->priv;  	struct net_device *dev = info->dev; -	DEBUG(0, "ibmtr_release(0x%p)\n", link); +	dev_dbg(&link->dev, "ibmtr_release\n");  	if (link->win) {  		struct tok_info *ti = netdev_priv(dev);  		iounmap(ti->mmio); -		pcmcia_release_window(info->sram_win_handle); +		pcmcia_release_window(link, info->sram_win_handle);  	}  	pcmcia_disable_device(link);  } diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c index b12e69592d1..8a5ae3b182e 100644 --- a/drivers/net/pcmcia/nmclan_cs.c +++ b/drivers/net/pcmcia/nmclan_cs.c @@ -381,13 +381,6 @@ typedef struct _mace_private {  Private Global Variables  ---------------------------------------------------------------------------- */ -#ifdef PCMCIA_DEBUG -static char rcsid[] = -"nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao"; -static char *version = -DRV_NAME " " DRV_VERSION " (Roger C. Pao)"; -#endif -  static const char *if_names[]={      "Auto", "10baseT", "BNC",  }; @@ -406,12 +399,6 @@ MODULE_LICENSE("GPL");  /* 0=auto, 1=10baseT, 2 = 10base2, default=auto */  INT_MODULE_PARM(if_port, 0); -#ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -#else -#define DEBUG(n, args...) -#endif  /* ----------------------------------------------------------------------------  Function Prototypes @@ -462,8 +449,7 @@ static int nmclan_probe(struct pcmcia_device *link)      mace_private *lp;      struct net_device *dev; -    DEBUG(0, "nmclan_attach()\n"); -    DEBUG(1, "%s\n", rcsid); +    dev_dbg(&link->dev, "nmclan_attach()\n");      /* Create new ethernet device */      dev = alloc_etherdev(sizeof(mace_private)); @@ -477,10 +463,8 @@ static int nmclan_probe(struct pcmcia_device *link)      link->io.NumPorts1 = 32;      link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;      link->io.IOAddrLines = 5; -    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID; +    link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;      link->irq.Handler = mace_interrupt; -    link->irq.Instance = dev;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO;      link->conf.ConfigIndex = 1; @@ -507,7 +491,7 @@ static void nmclan_detach(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    DEBUG(0, "nmclan_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "nmclan_detach\n");      if (link->dev_node)  	unregister_netdev(dev); @@ -654,37 +638,40 @@ nmclan_config  	ethernet device available to the system.  ---------------------------------------------------------------------------- */ -#define CS_CHECK(fn, ret) \ -  do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int nmclan_config(struct pcmcia_device *link)  {    struct net_device *dev = link->priv;    mace_private *lp = netdev_priv(dev); -  tuple_t tuple; -  u_char buf[64]; -  int i, last_ret, last_fn; +  u8 *buf; +  size_t len; +  int i, ret;    unsigned int ioaddr; -  DEBUG(0, "nmclan_config(0x%p)\n", link); +  dev_dbg(&link->dev, "nmclan_config\n"); + +  ret = pcmcia_request_io(link, &link->io); +  if (ret) +	  goto failed; +  ret = pcmcia_request_irq(link, &link->irq); +  if (ret) +	  goto failed; +  ret = pcmcia_request_configuration(link, &link->conf); +  if (ret) +	  goto failed; -  CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io)); -  CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -  CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));    dev->irq = link->irq.AssignedIRQ;    dev->base_addr = link->io.BasePort1;    ioaddr = dev->base_addr;    /* Read the ethernet address from the CIS. */ -  tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */; -  tuple.TupleData = buf; -  tuple.TupleDataMax = 64; -  tuple.TupleOffset = 0; -  tuple.Attributes = 0; -  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); -  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); -  memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN); +  len = pcmcia_get_tuple(link, 0x80, &buf); +  if (!buf || len < ETHER_ADDR_LEN) { +	  kfree(buf); +	  goto failed; +  } +  memcpy(dev->dev_addr, buf, ETHER_ADDR_LEN); +  kfree(buf);    /* Verify configuration by reading the MACE ID. */    { @@ -693,7 +680,7 @@ static int nmclan_config(struct pcmcia_device *link)      sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL);      sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH);      if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) { -      DEBUG(0, "nmclan_cs configured: mace id=%x %x\n", +      dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n",  	    sig[0], sig[1]);      } else {        printk(KERN_NOTICE "nmclan_cs: mace id not found: %x %x should" @@ -712,7 +699,7 @@ static int nmclan_config(struct pcmcia_device *link)      printk(KERN_NOTICE "nmclan_cs: invalid if_port requested\n");    link->dev_node = &lp->node; -  SET_NETDEV_DEV(dev, &handle_to_dev(link)); +  SET_NETDEV_DEV(dev, &link->dev);    i = register_netdev(dev);    if (i != 0) { @@ -729,8 +716,6 @@ static int nmclan_config(struct pcmcia_device *link)  	 dev->dev_addr);    return 0; -cs_failed: -	cs_error(link, last_fn, last_ret);  failed:  	nmclan_release(link);  	return -ENODEV; @@ -744,7 +729,7 @@ nmclan_release  ---------------------------------------------------------------------------- */  static void nmclan_release(struct pcmcia_device *link)  { -	DEBUG(0, "nmclan_release(0x%p)\n", link); +	dev_dbg(&link->dev, "nmclan_release\n");  	pcmcia_disable_device(link);  } @@ -795,7 +780,7 @@ static void nmclan_reset(struct net_device *dev)    /* Reset Xilinx */    reg.Action = CS_WRITE;    reg.Offset = CISREG_COR; -  DEBUG(1, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n", +  dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%lX, resetting...\n",  	OrigCorValue);    reg.Value = COR_SOFT_RESET;    pcmcia_access_configuration_register(link, ®); @@ -872,7 +857,7 @@ static int mace_close(struct net_device *dev)    mace_private *lp = netdev_priv(dev);    struct pcmcia_device *link = lp->p_dev; -  DEBUG(2, "%s: shutting down ethercard.\n", dev->name); +  dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name);    /* Mask off all interrupts from the MACE chip. */    outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR); @@ -891,24 +876,8 @@ static void netdev_get_drvinfo(struct net_device *dev,  	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);  } -#ifdef PCMCIA_DEBUG -static u32 netdev_get_msglevel(struct net_device *dev) -{ -	return pc_debug; -} - -static void netdev_set_msglevel(struct net_device *dev, u32 level) -{ -	pc_debug = level; -} -#endif /* PCMCIA_DEBUG */ -  static const struct ethtool_ops netdev_ethtool_ops = {  	.get_drvinfo		= netdev_get_drvinfo, -#ifdef PCMCIA_DEBUG -	.get_msglevel		= netdev_get_msglevel, -	.set_msglevel		= netdev_set_msglevel, -#endif /* PCMCIA_DEBUG */  };  /* ---------------------------------------------------------------------------- @@ -946,7 +915,7 @@ static netdev_tx_t mace_start_xmit(struct sk_buff *skb,    netif_stop_queue(dev); -  DEBUG(3, "%s: mace_start_xmit(length = %ld) called.\n", +  pr_debug("%s: mace_start_xmit(length = %ld) called.\n",  	dev->name, (long)skb->len);  #if (!TX_INTERRUPTABLE) @@ -1008,7 +977,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)    int IntrCnt = MACE_MAX_IR_ITERATIONS;    if (dev == NULL) { -    DEBUG(2, "mace_interrupt(): irq 0x%X for unknown device.\n", +    pr_debug("mace_interrupt(): irq 0x%X for unknown device.\n",  	  irq);      return IRQ_NONE;    } @@ -1031,7 +1000,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)    }    if (!netif_device_present(dev)) { -    DEBUG(2, "%s: interrupt from dead card\n", dev->name); +    pr_debug("%s: interrupt from dead card\n", dev->name);      return IRQ_NONE;    } @@ -1039,7 +1008,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)      /* WARNING: MACE_IR is a READ/CLEAR port! */      status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR); -    DEBUG(3, "mace_interrupt: irq 0x%X status 0x%X.\n", irq, status); +    pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status);      if (status & MACE_IR_RCVINT) {        mace_rx(dev, MACE_MAX_RX_ITERATIONS); @@ -1158,7 +1127,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)    ) {      rx_status = inw(ioaddr + AM2150_RCV); -    DEBUG(3, "%s: in mace_rx(), framecnt 0x%X, rx_status" +    pr_debug("%s: in mace_rx(), framecnt 0x%X, rx_status"  	  " 0x%X.\n", dev->name, rx_framecnt, rx_status);      if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */ @@ -1185,7 +1154,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)        lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV);          /* rcv collision count */ -      DEBUG(3, "    receiving packet size 0x%X rx_status" +      pr_debug("    receiving packet size 0x%X rx_status"  	    " 0x%X.\n", pkt_len, rx_status);        skb = dev_alloc_skb(pkt_len+2); @@ -1204,7 +1173,7 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)  	outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */  	continue;        } else { -	DEBUG(1, "%s: couldn't allocate a sk_buff of size" +	pr_debug("%s: couldn't allocate a sk_buff of size"  	      " %d.\n", dev->name, pkt_len);  	lp->linux_stats.rx_dropped++;        } @@ -1220,28 +1189,28 @@ pr_linux_stats  ---------------------------------------------------------------------------- */  static void pr_linux_stats(struct net_device_stats *pstats)  { -  DEBUG(2, "pr_linux_stats\n"); -  DEBUG(2, " rx_packets=%-7ld        tx_packets=%ld\n", +  pr_debug("pr_linux_stats\n"); +  pr_debug(" rx_packets=%-7ld        tx_packets=%ld\n",  	(long)pstats->rx_packets, (long)pstats->tx_packets); -  DEBUG(2, " rx_errors=%-7ld         tx_errors=%ld\n", +  pr_debug(" rx_errors=%-7ld         tx_errors=%ld\n",  	(long)pstats->rx_errors, (long)pstats->tx_errors); -  DEBUG(2, " rx_dropped=%-7ld        tx_dropped=%ld\n", +  pr_debug(" rx_dropped=%-7ld        tx_dropped=%ld\n",  	(long)pstats->rx_dropped, (long)pstats->tx_dropped); -  DEBUG(2, " multicast=%-7ld         collisions=%ld\n", +  pr_debug(" multicast=%-7ld         collisions=%ld\n",  	(long)pstats->multicast, (long)pstats->collisions); -  DEBUG(2, " rx_length_errors=%-7ld  rx_over_errors=%ld\n", +  pr_debug(" rx_length_errors=%-7ld  rx_over_errors=%ld\n",  	(long)pstats->rx_length_errors, (long)pstats->rx_over_errors); -  DEBUG(2, " rx_crc_errors=%-7ld     rx_frame_errors=%ld\n", +  pr_debug(" rx_crc_errors=%-7ld     rx_frame_errors=%ld\n",  	(long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors); -  DEBUG(2, " rx_fifo_errors=%-7ld    rx_missed_errors=%ld\n", +  pr_debug(" rx_fifo_errors=%-7ld    rx_missed_errors=%ld\n",  	(long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors); -  DEBUG(2, " tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n", +  pr_debug(" tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n",  	(long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors); -  DEBUG(2, " tx_fifo_errors=%-7ld    tx_heartbeat_errors=%ld\n", +  pr_debug(" tx_fifo_errors=%-7ld    tx_heartbeat_errors=%ld\n",  	(long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors); -  DEBUG(2, " tx_window_errors=%ld\n", +  pr_debug(" tx_window_errors=%ld\n",  	(long)pstats->tx_window_errors);  } /* pr_linux_stats */ @@ -1250,48 +1219,48 @@ pr_mace_stats  ---------------------------------------------------------------------------- */  static void pr_mace_stats(mace_statistics *pstats)  { -  DEBUG(2, "pr_mace_stats\n"); +  pr_debug("pr_mace_stats\n"); -  DEBUG(2, " xmtsv=%-7d             uflo=%d\n", +  pr_debug(" xmtsv=%-7d             uflo=%d\n",  	pstats->xmtsv, pstats->uflo); -  DEBUG(2, " lcol=%-7d              more=%d\n", +  pr_debug(" lcol=%-7d              more=%d\n",  	pstats->lcol, pstats->more); -  DEBUG(2, " one=%-7d               defer=%d\n", +  pr_debug(" one=%-7d               defer=%d\n",  	pstats->one, pstats->defer); -  DEBUG(2, " lcar=%-7d              rtry=%d\n", +  pr_debug(" lcar=%-7d              rtry=%d\n",  	pstats->lcar, pstats->rtry);    /* MACE_XMTRC */ -  DEBUG(2, " exdef=%-7d             xmtrc=%d\n", +  pr_debug(" exdef=%-7d             xmtrc=%d\n",  	pstats->exdef, pstats->xmtrc);    /* RFS1--Receive Status (RCVSTS) */ -  DEBUG(2, " oflo=%-7d              clsn=%d\n", +  pr_debug(" oflo=%-7d              clsn=%d\n",  	pstats->oflo, pstats->clsn); -  DEBUG(2, " fram=%-7d              fcs=%d\n", +  pr_debug(" fram=%-7d              fcs=%d\n",  	pstats->fram, pstats->fcs);    /* RFS2--Runt Packet Count (RNTPC) */    /* RFS3--Receive Collision Count (RCVCC) */ -  DEBUG(2, " rfs_rntpc=%-7d         rfs_rcvcc=%d\n", +  pr_debug(" rfs_rntpc=%-7d         rfs_rcvcc=%d\n",  	pstats->rfs_rntpc, pstats->rfs_rcvcc);    /* MACE_IR */ -  DEBUG(2, " jab=%-7d               babl=%d\n", +  pr_debug(" jab=%-7d               babl=%d\n",  	pstats->jab, pstats->babl); -  DEBUG(2, " cerr=%-7d              rcvcco=%d\n", +  pr_debug(" cerr=%-7d              rcvcco=%d\n",  	pstats->cerr, pstats->rcvcco); -  DEBUG(2, " rntpco=%-7d            mpco=%d\n", +  pr_debug(" rntpco=%-7d            mpco=%d\n",  	pstats->rntpco, pstats->mpco);    /* MACE_MPC */ -  DEBUG(2, " mpc=%d\n", pstats->mpc); +  pr_debug(" mpc=%d\n", pstats->mpc);    /* MACE_RNTPC */ -  DEBUG(2, " rntpc=%d\n", pstats->rntpc); +  pr_debug(" rntpc=%d\n", pstats->rntpc);    /* MACE_RCVCC */ -  DEBUG(2, " rcvcc=%d\n", pstats->rcvcc); +  pr_debug(" rcvcc=%d\n", pstats->rcvcc);  } /* pr_mace_stats */ @@ -1360,7 +1329,7 @@ static struct net_device_stats *mace_get_stats(struct net_device *dev)    update_stats(dev->base_addr, dev); -  DEBUG(1, "%s: updating the statistics.\n", dev->name); +  pr_debug("%s: updating the statistics.\n", dev->name);    pr_linux_stats(&lp->linux_stats);    pr_mace_stats(&lp->mace_stats); @@ -1427,7 +1396,7 @@ static void BuildLAF(int *ladrf, int *adr)    ladrf[byte] |= (1 << (hashcode & 7));  #ifdef PCMCIA_DEBUG -  if (pc_debug > 2) +  if (0)      printk(KERN_DEBUG "    adr =%pM\n", adr);    printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode);    for (i = 0; i < 8; i++) @@ -1454,12 +1423,12 @@ static void restore_multicast_list(struct net_device *dev)    unsigned int ioaddr = dev->base_addr;    int i; -  DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", +  pr_debug("%s: restoring Rx mode to %d addresses.\n",  	dev->name, num_addrs);    if (num_addrs > 0) { -    DEBUG(1, "Attempt to restore multicast list detected.\n"); +    pr_debug("Attempt to restore multicast list detected.\n");      mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR);      /* Poll ADDRCHG bit */ @@ -1511,11 +1480,11 @@ static void set_multicast_list(struct net_device *dev)    struct dev_mc_list *dmi = dev->mc_list;  #ifdef PCMCIA_DEBUG -  if (pc_debug > 1) { +  {      static int old;      if (dev->mc_count != old) {        old = dev->mc_count; -      DEBUG(0, "%s: setting Rx mode to %d addresses.\n", +      pr_debug("%s: setting Rx mode to %d addresses.\n",  	    dev->name, old);      }    } @@ -1546,7 +1515,7 @@ static void restore_multicast_list(struct net_device *dev)    unsigned int ioaddr = dev->base_addr;    mace_private *lp = netdev_priv(dev); -  DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name, +  pr_debug("%s: restoring Rx mode to %d addresses.\n", dev->name,  	lp->multicast_num_addrs);    if (dev->flags & IFF_PROMISC) { @@ -1567,11 +1536,11 @@ static void set_multicast_list(struct net_device *dev)    mace_private *lp = netdev_priv(dev);  #ifdef PCMCIA_DEBUG -  if (pc_debug > 1) { +  {      static int old;      if (dev->mc_count != old) {        old = dev->mc_count; -      DEBUG(0, "%s: setting Rx mode to %d addresses.\n", +      pr_debug("%s: setting Rx mode to %d addresses.\n",  	    dev->name, old);      }    } diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c index 347eaee855c..2d26b6ca28b 100644 --- a/drivers/net/pcmcia/pcnet_cs.c +++ b/drivers/net/pcmcia/pcnet_cs.c @@ -71,15 +71,6 @@  static const char *if_names[] = { "auto", "10baseT", "10base2"}; -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"pcnet_cs.c 1.153 2003/11/09 18:53:09 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -265,7 +256,7 @@ static int pcnet_probe(struct pcmcia_device *link)      pcnet_dev_t *info;      struct net_device *dev; -    DEBUG(0, "pcnet_attach()\n"); +    dev_dbg(&link->dev, "pcnet_attach()\n");      /* Create new ethernet device */      dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); @@ -275,7 +266,6 @@ static int pcnet_probe(struct pcmcia_device *link)      link->priv = dev;      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO; @@ -297,7 +287,7 @@ static void pcnet_detach(struct pcmcia_device *link)  {  	struct net_device *dev = link->priv; -	DEBUG(0, "pcnet_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "pcnet_detach\n");  	if (link->dev_node)  		unregister_netdev(dev); @@ -326,17 +316,15 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)      req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;      req.Base = 0; req.Size = 0;      req.AccessSpeed = 0; -    i = pcmcia_request_window(&link, &req, &link->win); -    if (i != 0) { -	cs_error(link, RequestWindow, i); +    i = pcmcia_request_window(link, &req, &link->win); +    if (i != 0)  	return NULL; -    }      virt = ioremap(req.Base, req.Size);      mem.Page = 0;      for (i = 0; i < NR_INFO; i++) {  	mem.CardOffset = hw_info[i].offset & ~(req.Size-1); -	pcmcia_map_mem_page(link->win, &mem); +	pcmcia_map_mem_page(link, link->win, &mem);  	base = &virt[hw_info[i].offset & (req.Size-1)];  	if ((readb(base+0) == hw_info[i].a0) &&  	    (readb(base+2) == hw_info[i].a1) && @@ -348,9 +336,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)      }      iounmap(virt); -    j = pcmcia_release_window(link->win); -    if (j != 0) -	cs_error(link, ReleaseWindow, j); +    j = pcmcia_release_window(link, link->win);      return (i < NR_INFO) ? hw_info+i : NULL;  } /* get_hwinfo */ @@ -495,9 +481,6 @@ static hw_info_t *get_hwired(struct pcmcia_device *link)  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int try_io_port(struct pcmcia_device *link)  {      int j, ret; @@ -567,19 +550,19 @@ static int pcnet_config(struct pcmcia_device *link)  {      struct net_device *dev = link->priv;      pcnet_dev_t *info = PRIV(dev); -    int last_ret, last_fn, start_pg, stop_pg, cm_offset; +    int ret, start_pg, stop_pg, cm_offset;      int has_shmem = 0;      hw_info_t *local_hw_info; -    DEBUG(0, "pcnet_config(0x%p)\n", link); +    dev_dbg(&link->dev, "pcnet_config\n"); -    last_ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); -    if (last_ret) { -	cs_error(link, RequestIO, last_ret); +    ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem); +    if (ret)  	goto failed; -    } -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed;      if (link->io.NumPorts2 == 8) {  	link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -589,7 +572,9 @@ static int pcnet_config(struct pcmcia_device *link)  	(link->card_id == PRODID_IBM_HOME_AND_AWAY))  	link->conf.ConfigIndex |= 0x10; -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      dev->irq = link->irq.AssignedIRQ;      dev->base_addr = link->io.BasePort1;      if (info->flags & HAS_MISC_REG) { @@ -660,7 +645,7 @@ static int pcnet_config(struct pcmcia_device *link)  	mii_phy_probe(dev);      link->dev_node = &info->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if (register_netdev(dev) != 0) {  	printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n"); @@ -687,8 +672,6 @@ static int pcnet_config(struct pcmcia_device *link)      printk(" hw_addr %pM\n", dev->dev_addr);      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      pcnet_release(link);      return -ENODEV; @@ -706,7 +689,7 @@ static void pcnet_release(struct pcmcia_device *link)  {  	pcnet_dev_t *info = PRIV(link->priv); -	DEBUG(0, "pcnet_release(0x%p)\n", link); +	dev_dbg(&link->dev, "pcnet_release\n");  	if (info->flags & USE_SHMEM)  		iounmap(info->base); @@ -960,7 +943,7 @@ static void mii_phy_probe(struct net_device *dev)  	phyid = tmp << 16;  	phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);  	phyid &= MII_PHYID_REV_MASK; -	DEBUG(0, "%s: MII at %d is 0x%08x\n", dev->name, i, phyid); +	pr_debug("%s: MII at %d is 0x%08x\n", dev->name, i, phyid);  	if (phyid == AM79C9XX_HOME_PHY) {  	    info->pna_phy = i;  	} else if (phyid != AM79C9XX_ETH_PHY) { @@ -976,7 +959,7 @@ static int pcnet_open(struct net_device *dev)      struct pcmcia_device *link = info->p_dev;      unsigned int nic_base = dev->base_addr; -    DEBUG(2, "pcnet_open('%s')\n", dev->name); +    dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name);      if (!pcmcia_dev_present(link))  	return -ENODEV; @@ -1008,7 +991,7 @@ static int pcnet_close(struct net_device *dev)      pcnet_dev_t *info = PRIV(dev);      struct pcmcia_device *link = info->p_dev; -    DEBUG(2, "pcnet_close('%s')\n", dev->name); +    dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);      ei_close(dev);      free_irq(dev->irq, dev); @@ -1251,10 +1234,8 @@ static void dma_block_input(struct net_device *dev, int count,      int xfer_count = count;      char *buf = skb->data; -#ifdef PCMCIA_DEBUG      if ((ei_debug > 4) && (count != 4)) -	printk(KERN_DEBUG "%s: [bi=%d]\n", dev->name, count+4); -#endif +	pr_debug("%s: [bi=%d]\n", dev->name, count+4);      if (ei_status.dmaing) {  	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."  	       "[DMAstat:%1x][irqlock:%1x]\n", @@ -1495,7 +1476,7 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,      pcnet_dev_t *info = PRIV(dev);      win_req_t req;      memreq_t mem; -    int i, window_size, offset, last_ret, last_fn; +    int i, window_size, offset, ret;      window_size = (stop_pg - start_pg) << 8;      if (window_size > 32 * 1024) @@ -1509,13 +1490,17 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,      req.Attributes |= WIN_USE_WAIT;      req.Base = 0; req.Size = window_size;      req.AccessSpeed = mem_speed; -    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); +    ret = pcmcia_request_window(link, &req, &link->win); +    if (ret) +	    goto failed;      mem.CardOffset = (start_pg << 8) + cm_offset;      offset = mem.CardOffset % window_size;      mem.CardOffset -= offset;      mem.Page = 0; -    CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); +    ret = pcmcia_map_mem_page(link, link->win, &mem); +    if (ret) +	    goto failed;      /* Try scribbling on the buffer */      info->base = ioremap(req.Base, window_size); @@ -1527,8 +1512,8 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,      pcnet_reset_8390(dev);      if (i != (TX_PAGES<<8)) {  	iounmap(info->base); -	pcmcia_release_window(link->win); -	info->base = NULL; link->win = NULL; +	pcmcia_release_window(link, link->win); +	info->base = NULL; link->win = 0;  	goto failed;      } @@ -1549,8 +1534,6 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,      info->flags |= USE_SHMEM;      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      return 1;  } @@ -1795,7 +1778,6 @@ static int __init init_pcnet_cs(void)  static void __exit exit_pcnet_cs(void)  { -    DEBUG(0, "pcnet_cs: unloading\n");      pcmcia_unregister_driver(&pcnet_driver);  } diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c index 117b083a10c..cc4853bc025 100644 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ b/drivers/net/pcmcia/smc91c92_cs.c @@ -79,14 +79,6 @@ MODULE_FIRMWARE(FIRMWARE_NAME);  */  INT_MODULE_PARM(if_port, 0); -#ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -static const char *version = -"smc91c92_cs.c 1.123 2006/11/09 Donald Becker, becker@scyld.com.\n"; -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -#else -#define DEBUG(n, args...) -#endif  #define DRV_NAME	"smc91c92_cs"  #define DRV_VERSION	"1.123" @@ -126,12 +118,6 @@ struct smc_private {      int				rx_ovrn;  }; -struct smc_cfg_mem { -    tuple_t tuple; -    cisparse_t parse; -    u_char buf[255]; -}; -  /* Special definitions for Megahertz multifunction cards */  #define MEGAHERTZ_ISR		0x0380 @@ -329,7 +315,7 @@ static int smc91c92_probe(struct pcmcia_device *link)      struct smc_private *smc;      struct net_device *dev; -    DEBUG(0, "smc91c92_attach()\n"); +    dev_dbg(&link->dev, "smc91c92_attach()\n");      /* Create new ethernet device */      dev = alloc_etherdev(sizeof(struct smc_private)); @@ -343,10 +329,8 @@ static int smc91c92_probe(struct pcmcia_device *link)      link->io.NumPorts1 = 16;      link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;      link->io.IOAddrLines = 4; -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID; +    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;      link->irq.Handler = &smc_interrupt; -    link->irq.Instance = dev;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO; @@ -377,7 +361,7 @@ static void smc91c92_detach(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    DEBUG(0, "smc91c92_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "smc91c92_detach\n");      if (link->dev_node)  	unregister_netdev(dev); @@ -408,34 +392,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s)      return 0;  } -/*====================================================================*/ - -static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, -		cisparse_t *parse) -{ -	int i; - -	i = pcmcia_get_first_tuple(handle, tuple); -	if (i != 0) -		return i; -	i = pcmcia_get_tuple_data(handle, tuple); -	if (i != 0) -		return i; -	return pcmcia_parse_tuple(tuple, parse); -} - -static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, -		cisparse_t *parse) -{ -	int i; - -	if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 || -			(i = pcmcia_get_tuple_data(handle, tuple)) != 0) -		return i; -	return pcmcia_parse_tuple(tuple, parse); -} - -/*====================================================================== +/*====================================================================      Configuration stuff for Megahertz cards @@ -490,19 +447,14 @@ static int mhz_mfc_config(struct pcmcia_device *link)  {      struct net_device *dev = link->priv;      struct smc_private *smc = netdev_priv(dev); -    struct smc_cfg_mem *cfg_mem;      win_req_t req;      memreq_t mem;      int i; -    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); -    if (!cfg_mem) -	    return -ENOMEM; -      link->conf.Attributes |= CONF_ENABLE_SPKR;      link->conf.Status = CCSR_AUDIO_ENA;      link->irq.Attributes = -	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; +	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;      link->io.IOAddrLines = 16;      link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;      link->io.NumPorts2 = 8; @@ -510,91 +462,80 @@ static int mhz_mfc_config(struct pcmcia_device *link)      /* The Megahertz combo cards have modem-like CIS entries, so         we have to explicitly try a bunch of port combinations. */      if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL)) -	goto free_cfg_mem; +	    return -ENODEV; +      dev->base_addr = link->io.BasePort1;      /* Allocate a memory window, for accessing the ISR */      req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;      req.Base = req.Size = 0;      req.AccessSpeed = 0; -    i = pcmcia_request_window(&link, &req, &link->win); +    i = pcmcia_request_window(link, &req, &link->win);      if (i != 0) -	goto free_cfg_mem; +	    return -ENODEV; +      smc->base = ioremap(req.Base, req.Size);      mem.CardOffset = mem.Page = 0;      if (smc->manfid == MANFID_MOTOROLA)  	mem.CardOffset = link->conf.ConfigBase; -    i = pcmcia_map_mem_page(link->win, &mem); +    i = pcmcia_map_mem_page(link, link->win, &mem);      if ((i == 0) &&  	(smc->manfid == MANFID_MEGAHERTZ) &&  	(smc->cardid == PRODID_MEGAHERTZ_EM3288))  	    mhz_3288_power(link); -free_cfg_mem: -    kfree(cfg_mem); -    return -ENODEV; +    return 0;  } -static int mhz_setup(struct pcmcia_device *link) +static int pcmcia_get_versmac(struct pcmcia_device *p_dev, +			      tuple_t *tuple, +			      void *priv)  { -    struct net_device *dev = link->priv; -    struct smc_cfg_mem *cfg_mem; -    tuple_t *tuple; -    cisparse_t *parse; -    u_char *buf, *station_addr; -    int rc; +	struct net_device *dev = priv; +	cisparse_t parse; -    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); -    if (!cfg_mem) -	return -1; +	if (pcmcia_parse_tuple(tuple, &parse)) +		return -EINVAL; -    tuple = &cfg_mem->tuple; -    parse = &cfg_mem->parse; -    buf = cfg_mem->buf; +	if ((parse.version_1.ns > 3) && +	    (cvt_ascii_address(dev, +			       (parse.version_1.str + parse.version_1.ofs[3])))) +		return 0; -    tuple->Attributes = tuple->TupleOffset = 0; -    tuple->TupleData = (cisdata_t *)buf; -    tuple->TupleDataMax = 255; +	return -EINVAL; +}; + +static int mhz_setup(struct pcmcia_device *link) +{ +    struct net_device *dev = link->priv; +    size_t len; +    u8 *buf; +    int rc;      /* Read the station address from the CIS.  It is stored as the last         (fourth) string in the Version 1 Version/ID tuple. */ -    tuple->DesiredTuple = CISTPL_VERS_1; -    if (first_tuple(link, tuple, parse) != 0) { -	rc = -1; -	goto free_cfg_mem; -    } +    if ((link->prod_id[3]) && +	(cvt_ascii_address(dev, link->prod_id[3]) == 0)) +	    return 0; + +    /* Workarounds for broken cards start here. */      /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ -    if (next_tuple(link, tuple, parse) != 0) -	first_tuple(link, tuple, parse); -    if (parse->version_1.ns > 3) { -	station_addr = parse->version_1.str + parse->version_1.ofs[3]; -	if (cvt_ascii_address(dev, station_addr) == 0) { -		rc = 0; -		goto free_cfg_mem; -	} -    } +    if (!pcmcia_loop_tuple(link, CISTPL_VERS_1, pcmcia_get_versmac, dev)) +	    return 0;      /* Another possibility: for the EM3288, in a special tuple */ -    tuple->DesiredTuple = 0x81; -    if (pcmcia_get_first_tuple(link, tuple) != 0) { -	rc = -1; -	goto free_cfg_mem; -    } -    if (pcmcia_get_tuple_data(link, tuple) != 0) { -	rc = -1; -	goto free_cfg_mem; -    } -    buf[12] = '\0'; -    if (cvt_ascii_address(dev, buf) == 0) { -	rc = 0; -	goto free_cfg_mem; -   }      rc = -1; -free_cfg_mem: -   kfree(cfg_mem); -   return rc; -} +    len = pcmcia_get_tuple(link, 0x81, &buf); +    if (buf && len >= 13) { +	    buf[12] = '\0'; +	    if (cvt_ascii_address(dev, buf)) +		    rc = 0; +    } +    kfree(buf); + +    return rc; +};  /*====================================================================== @@ -684,58 +625,21 @@ static int smc_config(struct pcmcia_device *link)      return i;  } +  static int smc_setup(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    struct smc_cfg_mem *cfg_mem; -    tuple_t *tuple; -    cisparse_t *parse; -    cistpl_lan_node_id_t *node_id; -    u_char *buf, *station_addr; -    int i, rc; - -    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); -    if (!cfg_mem) -	    return -ENOMEM; - -    tuple = &cfg_mem->tuple; -    parse = &cfg_mem->parse; -    buf = cfg_mem->buf; - -    tuple->Attributes = tuple->TupleOffset = 0; -    tuple->TupleData = (cisdata_t *)buf; -    tuple->TupleDataMax = 255;      /* Check for a LAN function extension tuple */ -    tuple->DesiredTuple = CISTPL_FUNCE; -    i = first_tuple(link, tuple, parse); -    while (i == 0) { -	if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID) -	    break; -	i = next_tuple(link, tuple, parse); -    } -    if (i == 0) { -	node_id = (cistpl_lan_node_id_t *)parse->funce.data; -	if (node_id->nb == 6) { -	    for (i = 0; i < 6; i++) -		dev->dev_addr[i] = node_id->id[i]; -	    rc = 0; -	    goto free_cfg_mem; -	} -    } +    if (!pcmcia_get_mac_from_cis(link, dev)) +	    return 0; +      /* Try the third string in the Version 1 Version/ID tuple. */      if (link->prod_id[2]) { -	station_addr = link->prod_id[2]; -	if (cvt_ascii_address(dev, station_addr) == 0) { -		rc = 0; -		goto free_cfg_mem; -	} +	    if (cvt_ascii_address(dev, link->prod_id[2]) == 0) +		    return 0;      } - -    rc = -1; -free_cfg_mem: -    kfree(cfg_mem); -    return rc; +    return -1;  }  /*====================================================================*/ @@ -749,7 +653,7 @@ static int osi_config(struct pcmcia_device *link)      link->conf.Attributes |= CONF_ENABLE_SPKR;      link->conf.Status = CCSR_AUDIO_ENA;      link->irq.Attributes = -	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT; +	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;      link->io.NumPorts1 = 64;      link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;      link->io.NumPorts2 = 8; @@ -794,41 +698,31 @@ static int osi_load_firmware(struct pcmcia_device *link)  	return err;  } -static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) +static int pcmcia_osi_mac(struct pcmcia_device *p_dev, +			  tuple_t *tuple, +			  void *priv)  { -    struct net_device *dev = link->priv; -    struct smc_cfg_mem *cfg_mem; -    tuple_t *tuple; -    u_char *buf; -    int i, rc; +	struct net_device *dev = priv; +	int i; -    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL); -    if (!cfg_mem) -        return -1; +	if (tuple->TupleDataLen < 8) +		return -EINVAL; +	if (tuple->TupleData[0] != 0x04) +		return -EINVAL; +	for (i = 0; i < 6; i++) +		dev->dev_addr[i] = tuple->TupleData[i+2]; +	return 0; +}; -    tuple = &cfg_mem->tuple; -    buf = cfg_mem->buf; -    tuple->Attributes = TUPLE_RETURN_COMMON; -    tuple->TupleData = (cisdata_t *)buf; -    tuple->TupleDataMax = 255; -    tuple->TupleOffset = 0; +static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) +{ +    struct net_device *dev = link->priv; +    int rc;      /* Read the station address from tuple 0x90, subtuple 0x04 */ -    tuple->DesiredTuple = 0x90; -    i = pcmcia_get_first_tuple(link, tuple); -    while (i == 0) { -	i = pcmcia_get_tuple_data(link, tuple); -	if ((i != 0) || (buf[0] == 0x04)) -	    break; -	i = pcmcia_get_next_tuple(link, tuple); -    } -    if (i != 0) { -	rc = -1; -	goto free_cfg_mem; -    } -    for (i = 0; i < 6; i++) -	dev->dev_addr[i] = buf[i+2]; +    if (pcmcia_loop_tuple(link, 0x90, pcmcia_osi_mac, dev)) +	    return -1;      if (((manfid == MANFID_OSITECH) &&  	 (cardid == PRODID_OSITECH_SEVEN)) || @@ -836,20 +730,17 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)  	 (cardid == PRODID_PSION_NET100))) {  	rc = osi_load_firmware(link);  	if (rc) -		goto free_cfg_mem; +		return rc;      } else if (manfid == MANFID_OSITECH) {  	/* Make sure both functions are powered up */  	set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);  	/* Now, turn on the interrupt for both card functions */  	set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR); -	DEBUG(2, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n", +	dev_dbg(&link->dev, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n",  	      inw(link->io.BasePort1 + OSITECH_AUI_PWR),  	      inw(link->io.BasePort1 + OSITECH_RESET_ISR));      } -    rc = 0; -free_cfg_mem: -   kfree(cfg_mem); -   return rc; +    return 0;  }  static int smc91c92_suspend(struct pcmcia_device *link) @@ -959,12 +850,6 @@ static int check_sig(struct pcmcia_device *link)  ======================================================================*/ -#define CS_EXIT_TEST(ret, svc, label)	\ -if (ret != 0) {				\ -	cs_error(link, svc, ret);	\ -	goto label; 			\ -} -  static int smc91c92_config(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; @@ -974,7 +859,7 @@ static int smc91c92_config(struct pcmcia_device *link)      unsigned int ioaddr;      u_long mir; -    DEBUG(0, "smc91c92_config(0x%p)\n", link); +    dev_dbg(&link->dev, "smc91c92_config\n");      smc->manfid = link->manf_id;      smc->cardid = link->card_id; @@ -990,12 +875,15 @@ static int smc91c92_config(struct pcmcia_device *link)      } else {  	i = smc_config(link);      } -    CS_EXIT_TEST(i, RequestIO, config_failed); +    if (i) +	    goto config_failed;      i = pcmcia_request_irq(link, &link->irq); -    CS_EXIT_TEST(i, RequestIRQ, config_failed); +    if (i) +	    goto config_failed;      i = pcmcia_request_configuration(link, &link->conf); -    CS_EXIT_TEST(i, RequestConfiguration, config_failed); +    if (i) +	    goto config_failed;      if (smc->manfid == MANFID_MOTOROLA)  	mot_config(link); @@ -1074,7 +962,7 @@ static int smc91c92_config(struct pcmcia_device *link)      }      link->dev_node = &smc->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if (register_netdev(dev) != 0) {  	printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n"); @@ -1100,7 +988,7 @@ static int smc91c92_config(struct pcmcia_device *link)      if (smc->cfg & CFG_MII_SELECT) {  	if (smc->mii_if.phy_id != -1) { -	    DEBUG(0, "  MII transceiver at index %d, status %x.\n", +	    dev_dbg(&link->dev, "  MII transceiver at index %d, status %x.\n",  		  smc->mii_if.phy_id, j);  	} else {      	    printk(KERN_NOTICE "  No MII transceivers found!\n"); @@ -1110,7 +998,7 @@ static int smc91c92_config(struct pcmcia_device *link)  config_undo:      unregister_netdev(dev); -config_failed:			/* CS_EXIT_TEST() calls jump to here... */ +config_failed:      smc91c92_release(link);      return -ENODEV;  } /* smc91c92_config */ @@ -1125,7 +1013,7 @@ config_failed:			/* CS_EXIT_TEST() calls jump to here... */  static void smc91c92_release(struct pcmcia_device *link)  { -	DEBUG(0, "smc91c92_release(0x%p)\n", link); +	dev_dbg(&link->dev, "smc91c92_release\n");  	if (link->win) {  		struct net_device *dev = link->priv;  		struct smc_private *smc = netdev_priv(dev); @@ -1222,10 +1110,10 @@ static int smc_open(struct net_device *dev)      struct smc_private *smc = netdev_priv(dev);      struct pcmcia_device *link = smc->p_dev; -#ifdef PCMCIA_DEBUG -    DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n", +    dev_dbg(&link->dev, "%s: smc_open(%p), ID/Window %4.4x.\n",  	  dev->name, dev, inw(dev->base_addr + BANK_SELECT)); -    if (pc_debug > 1) smc_dump(dev); +#ifdef PCMCIA_DEBUG +    smc_dump(dev);  #endif      /* Check that the PCMCIA card is still here. */ @@ -1260,7 +1148,7 @@ static int smc_close(struct net_device *dev)      struct pcmcia_device *link = smc->p_dev;      unsigned int ioaddr = dev->base_addr; -    DEBUG(0, "%s: smc_close(), status %4.4x.\n", +    dev_dbg(&link->dev, "%s: smc_close(), status %4.4x.\n",  	  dev->name, inw(ioaddr + BANK_SELECT));      netif_stop_queue(dev); @@ -1327,7 +1215,7 @@ static void smc_hardware_send_packet(struct net_device * dev)  	u_char *buf = skb->data;  	u_int length = skb->len; /* The chip will pad to ethernet min. */ -	DEBUG(2, "%s: Trying to xmit packet of length %d.\n", +	pr_debug("%s: Trying to xmit packet of length %d.\n",  	      dev->name, length);  	/* send the packet length: +6 for status word, length, and ctl */ @@ -1382,7 +1270,7 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb,      netif_stop_queue(dev); -    DEBUG(2, "%s: smc_start_xmit(length = %d) called," +    pr_debug("%s: smc_start_xmit(length = %d) called,"  	  " status %4.4x.\n", dev->name, skb->len, inw(ioaddr + 2));      if (smc->saved_skb) { @@ -1429,7 +1317,7 @@ static netdev_tx_t smc_start_xmit(struct sk_buff *skb,      }      /* Otherwise defer until the Tx-space-allocated interrupt. */ -    DEBUG(2, "%s: memory allocation deferred.\n", dev->name); +    pr_debug("%s: memory allocation deferred.\n", dev->name);      outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT);      spin_unlock_irqrestore(&smc->lock, flags); @@ -1494,7 +1382,7 @@ static void smc_eph_irq(struct net_device *dev)      SMC_SELECT_BANK(0);      ephs = inw(ioaddr + EPH); -    DEBUG(2, "%s: Ethernet protocol handler interrupt, status" +    pr_debug("%s: Ethernet protocol handler interrupt, status"  	  " %4.4x.\n", dev->name, ephs);      /* Could be a counter roll-over warning: update stats. */      card_stats = inw(ioaddr + COUNTER); @@ -1534,7 +1422,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)      ioaddr = dev->base_addr; -    DEBUG(3, "%s: SMC91c92 interrupt %d at %#x.\n", dev->name, +    pr_debug("%s: SMC91c92 interrupt %d at %#x.\n", dev->name,  	  irq, ioaddr);      spin_lock(&smc->lock); @@ -1543,7 +1431,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)      if ((saved_bank & 0xff00) != 0x3300) {  	/* The device does not exist -- the card could be off-line, or  	   maybe it has been ejected. */ -	DEBUG(1, "%s: SMC91c92 interrupt %d for non-existent" +	pr_debug("%s: SMC91c92 interrupt %d for non-existent"  	      "/ejected device.\n", dev->name, irq);  	handled = 0;  	goto irq_done; @@ -1557,7 +1445,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)      do { /* read the status flag, and mask it */  	status = inw(ioaddr + INTERRUPT) & 0xff; -	DEBUG(3, "%s: Status is %#2.2x (mask %#2.2x).\n", dev->name, +	pr_debug("%s: Status is %#2.2x (mask %#2.2x).\n", dev->name,  	      status, mask);  	if ((status & mask) == 0) {  	    if (bogus_cnt == INTR_WORK) @@ -1602,7 +1490,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)  	    smc_eph_irq(dev);      } while (--bogus_cnt); -    DEBUG(3, "  Restoring saved registers mask %2.2x bank %4.4x" +    pr_debug("  Restoring saved registers mask %2.2x bank %4.4x"  	  " pointer %4.4x.\n", mask, saved_bank, saved_pointer);      /* restore state register */ @@ -1610,7 +1498,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)      outw(saved_pointer, ioaddr + POINTER);      SMC_SELECT_BANK(saved_bank); -    DEBUG(3, "%s: Exiting interrupt IRQ%d.\n", dev->name, irq); +    pr_debug("%s: Exiting interrupt IRQ%d.\n", dev->name, irq);  irq_done: @@ -1661,7 +1549,7 @@ static void smc_rx(struct net_device *dev)      rx_status = inw(ioaddr + DATA_1);      packet_length = inw(ioaddr + DATA_1) & 0x07ff; -    DEBUG(2, "%s: Receive status %4.4x length %d.\n", +    pr_debug("%s: Receive status %4.4x length %d.\n",  	  dev->name, rx_status, packet_length);      if (!(rx_status & RS_ERRORS)) {		 @@ -1672,7 +1560,7 @@ static void smc_rx(struct net_device *dev)  	skb = dev_alloc_skb(packet_length+2);  	if (skb == NULL) { -	    DEBUG(1, "%s: Low memory, packet dropped.\n", dev->name); +	    pr_debug("%s: Low memory, packet dropped.\n", dev->name);  	    dev->stats.rx_dropped++;  	    outw(MC_RELEASE, ioaddr + MMU_CMD);  	    return; @@ -1832,7 +1720,7 @@ static void smc_reset(struct net_device *dev)      struct smc_private *smc = netdev_priv(dev);      int i; -    DEBUG(0, "%s: smc91c92 reset called.\n", dev->name); +    pr_debug("%s: smc91c92 reset called.\n", dev->name);      /* The first interaction must be a write to bring the chip out         of sleep mode. */ @@ -2149,18 +2037,6 @@ static u32 smc_get_link(struct net_device *dev)  	return ret;  } -#ifdef PCMCIA_DEBUG -static u32 smc_get_msglevel(struct net_device *dev) -{ -	return pc_debug; -} - -static void smc_set_msglevel(struct net_device *dev, u32 val) -{ -	pc_debug = val; -} -#endif -  static int smc_nway_reset(struct net_device *dev)  {  	struct smc_private *smc = netdev_priv(dev); @@ -2184,10 +2060,6 @@ static const struct ethtool_ops ethtool_ops = {  	.get_settings = smc_get_settings,  	.set_settings = smc_set_settings,  	.get_link = smc_get_link, -#ifdef PCMCIA_DEBUG -	.get_msglevel = smc_get_msglevel, -	.set_msglevel = smc_set_msglevel, -#endif  	.nway_reset = smc_nway_reset,  }; diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c index 187da21f720..a2eda28f903 100644 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ b/drivers/net/pcmcia/xirc2ps_cs.c @@ -211,20 +211,6 @@ enum xirc_cmd { 	    /* Commands */  static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; -/**************** - * All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If - * you do not define PCMCIA_DEBUG at all, all the debug code will be - * left out.  If you compile with PCMCIA_DEBUG=0, the debug code will - * be present but disabled -- but it can then be enabled for specific - * modules at load time with a 'pc_debug=#' option to insmod. - */ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KDBG_XIRC args) -#else -#define DEBUG(n, args...) -#endif  #define KDBG_XIRC KERN_DEBUG   "xirc2ps_cs: "  #define KERR_XIRC KERN_ERR     "xirc2ps_cs: " @@ -359,7 +345,7 @@ static void xirc_tx_timeout(struct net_device *dev);  static void xirc2ps_tx_timeout_task(struct work_struct *work);  static void set_addresses(struct net_device *dev);  static void set_multicast_list(struct net_device *dev); -static int set_card_type(struct pcmcia_device *link, const void *s); +static int set_card_type(struct pcmcia_device *link);  static int do_config(struct net_device *dev, struct ifmap *map);  static int do_open(struct net_device *dev);  static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); @@ -371,28 +357,6 @@ static void do_powerdown(struct net_device *dev);  static int do_stop(struct net_device *dev);  /*=============== Helper functions =========================*/ -static int -first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) -{ -	int err; - -	if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 && -			(err = pcmcia_get_tuple_data(handle, tuple)) == 0) -		err = pcmcia_parse_tuple(tuple, parse); -	return err; -} - -static int -next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse) -{ -	int err; - -	if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 && -			(err = pcmcia_get_tuple_data(handle, tuple)) == 0) -		err = pcmcia_parse_tuple(tuple, parse); -	return err; -} -  #define SelectPage(pgnr)   outb((pgnr), ioaddr + XIRCREG_PR)  #define GetByte(reg)	   ((unsigned)inb(ioaddr + (reg)))  #define GetWord(reg)	   ((unsigned)inw(ioaddr + (reg))) @@ -400,7 +364,7 @@ next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)  #define PutWord(reg,value) outw((value), ioaddr+(reg))  /*====== Functions used for debugging =================================*/ -#if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */ +#if 0 /* reading regs may change system status */  static void  PrintRegisters(struct net_device *dev)  { @@ -432,7 +396,7 @@ PrintRegisters(struct net_device *dev)  	}      }  } -#endif /* PCMCIA_DEBUG */ +#endif /* 0 */  /*============== MII Management functions ===============*/ @@ -576,7 +540,7 @@ xirc2ps_probe(struct pcmcia_device *link)      struct net_device *dev;      local_info_t *local; -    DEBUG(0, "attach()\n"); +    dev_dbg(&link->dev, "attach()\n");      /* Allocate the device structure */      dev = alloc_etherdev(sizeof(local_info_t)); @@ -592,7 +556,6 @@ xirc2ps_probe(struct pcmcia_device *link)      link->conf.IntType = INT_MEMORY_AND_IO;      link->conf.ConfigIndex = 1;      link->irq.Handler = xirc2ps_interrupt; -    link->irq.Instance = dev;      /* Fill in card specific entries */      dev->netdev_ops = &netdev_ops; @@ -615,7 +578,7 @@ xirc2ps_detach(struct pcmcia_device *link)  {      struct net_device *dev = link->priv; -    DEBUG(0, "detach(0x%p)\n", link); +    dev_dbg(&link->dev, "detach\n");      if (link->dev_node)  	unregister_netdev(dev); @@ -644,17 +607,25 @@ xirc2ps_detach(struct pcmcia_device *link)   *   */  static int -set_card_type(struct pcmcia_device *link, const void *s) +set_card_type(struct pcmcia_device *link)  {      struct net_device *dev = link->priv;      local_info_t *local = netdev_priv(dev); -  #ifdef PCMCIA_DEBUG -    unsigned cisrev = ((const unsigned char *)s)[2]; -  #endif -    unsigned mediaid= ((const unsigned char *)s)[3]; -    unsigned prodid = ((const unsigned char *)s)[4]; +    u8 *buf; +    unsigned int cisrev, mediaid, prodid; +    size_t len; + +    len = pcmcia_get_tuple(link, CISTPL_MANFID, &buf); +    if (len < 5) { +	    dev_err(&link->dev, "invalid CIS -- sorry\n"); +	    return 0; +    } + +    cisrev = buf[2]; +    mediaid = buf[3]; +    prodid = buf[4]; -    DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n", +    dev_dbg(&link->dev, "cisrev=%02x mediaid=%02x prodid=%02x\n",  	  cisrev, mediaid, prodid);      local->mohawk = 0; @@ -761,6 +732,26 @@ xirc2ps_config_check(struct pcmcia_device *p_dev,  } + +static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev, +			     tuple_t *tuple, +			     void *priv) +{ +	struct net_device *dev = priv; +	int i; + +	if (tuple->TupleDataLen != 13) +		return -EINVAL; +	if ((tuple->TupleData[0] != 2) || (tuple->TupleData[1] != 1) || +		(tuple->TupleData[2] != 6)) +		return -EINVAL; +	/* another try	(James Lehmer's CE2 version 4.1)*/ +	for (i = 2; i < 6; i++) +		dev->dev_addr[i] = tuple->TupleData[i+2]; +	return 0; +}; + +  /****************   * xirc2ps_config() is scheduled to run after a CARD_INSERTION event   * is received, to configure the PCMCIA socket, and to make the @@ -772,33 +763,21 @@ xirc2ps_config(struct pcmcia_device * link)      struct net_device *dev = link->priv;      local_info_t *local = netdev_priv(dev);      unsigned int ioaddr; -    tuple_t tuple; -    cisparse_t parse; -    int err, i; -    u_char buf[64]; -    cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data; +    int err; +    u8 *buf; +    size_t len;      local->dingo_ccr = NULL; -    DEBUG(0, "config(0x%p)\n", link); - -    /* -     * This reads the card's CONFIG tuple to find its configuration -     * registers. -     */ -    tuple.Attributes = 0; -    tuple.TupleData = buf; -    tuple.TupleDataMax = 64; -    tuple.TupleOffset = 0; +    dev_dbg(&link->dev, "config\n");      /* Is this a valid	card */ -    tuple.DesiredTuple = CISTPL_MANFID; -    if ((err=first_tuple(link, &tuple, &parse))) { +    if (link->has_manf_id == 0) {  	printk(KNOT_XIRC "manfid not found in CIS\n");  	goto failure;      } -    switch(parse.manfid.manf) { +    switch (link->manf_id) {        case MANFID_XIRCOM:  	local->manf_str = "Xircom";  	break; @@ -817,65 +796,44 @@ xirc2ps_config(struct pcmcia_device * link)  	break;        default:  	printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", -	       (unsigned)parse.manfid.manf); +	       (unsigned)link->manf_id);  	goto failure;      } -    DEBUG(0, "found %s card\n", local->manf_str); +    dev_dbg(&link->dev, "found %s card\n", local->manf_str); -    if (!set_card_type(link, buf)) { +    if (!set_card_type(link)) {  	printk(KNOT_XIRC "this card is not supported\n");  	goto failure;      }      /* get the ethernet address from the CIS */ -    tuple.DesiredTuple = CISTPL_FUNCE; -    for (err = first_tuple(link, &tuple, &parse); !err; -			     err = next_tuple(link, &tuple, &parse)) { -	/* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: -	 * the first one with a length of zero the second correct - -	 * so I skip all entries with length 0 */ -	    if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID && -		((cistpl_lan_node_id_t *)parse.funce.data)->nb) -		    break; -    } -    if (err) { /* not found: try to get the node-id from tuple 0x89 */ -	tuple.DesiredTuple = 0x89;  /* data layout looks like tuple 0x22 */ -	if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && -		(err = pcmcia_get_tuple_data(link, &tuple)) == 0) { -	    if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) -		memcpy(&parse, buf, 8); -	    else -		err = -1; -	} -    } -    if (err) { /* another try	(James Lehmer's CE2 version 4.1)*/ -	tuple.DesiredTuple = CISTPL_FUNCE; -	for (err = first_tuple(link, &tuple, &parse); !err; -				 err = next_tuple(link, &tuple, &parse)) { -		if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 && -		    parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { -		buf[1] = 4; -		memcpy(&parse, buf+1, 8); -		break; +    err = pcmcia_get_mac_from_cis(link, dev); + +    /* not found: try to get the node-id from tuple 0x89 */ +    if (err) { +	    len = pcmcia_get_tuple(link, 0x89, &buf); +	    /* data layout looks like tuple 0x22 */ +	    if (buf && len == 8) { +		    if (*buf == CISTPL_FUNCE_LAN_NODE_ID) { +			    int i; +			    for (i = 2; i < 6; i++) +				    dev->dev_addr[i] = buf[i+2]; +		    } else +			    err = -1;  	    } -	} +	    kfree(buf);      } + +    if (err) +	err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev); +      if (err) {  	printk(KNOT_XIRC "node-id not found in CIS\n");  	goto failure;      } -    node_id = (cistpl_lan_node_id_t *)parse.funce.data; -    if (node_id->nb != 6) { -	printk(KNOT_XIRC "malformed node-id in CIS\n"); -	goto failure; -    } -    for (i=0; i < 6; i++) -	dev->dev_addr[i] = node_id->id[i];      link->io.IOAddrLines =10;      link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -    link->irq.Attributes = IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      if (local->modem) {  	int pass; @@ -916,10 +874,8 @@ xirc2ps_config(struct pcmcia_device * link)  		goto port_found;  	}  	link->io.BasePort1 = 0; /* let CS decide */ -	if ((err=pcmcia_request_io(link, &link->io))) { -	    cs_error(link, RequestIO, err); +	if ((err=pcmcia_request_io(link, &link->io)))  	    goto config_error; -	}      }    port_found:      if (err) @@ -929,19 +885,15 @@ xirc2ps_config(struct pcmcia_device * link)       * Now allocate an interrupt line.	Note that this does not       * actually assign a handler to the interrupt.       */ -    if ((err=pcmcia_request_irq(link, &link->irq))) { -	cs_error(link, RequestIRQ, err); +    if ((err=pcmcia_request_irq(link, &link->irq)))  	goto config_error; -    }      /****************       * This actually configures the PCMCIA socket -- setting up       * the I/O windows and the interrupt mapping.       */ -    if ((err=pcmcia_request_configuration(link, &link->conf))) { -	cs_error(link, RequestConfiguration, err); +    if ((err=pcmcia_request_configuration(link, &link->conf)))  	goto config_error; -    }      if (local->dingo) {  	conf_reg_t reg; @@ -956,17 +908,13 @@ xirc2ps_config(struct pcmcia_device * link)  	reg.Action = CS_WRITE;  	reg.Offset = CISREG_IOBASE_0;  	reg.Value = link->io.BasePort2 & 0xff; -	if ((err = pcmcia_access_configuration_register(link, ®))) { -	    cs_error(link, AccessConfigurationRegister, err); +	if ((err = pcmcia_access_configuration_register(link, ®)))  	    goto config_error; -	}  	reg.Action = CS_WRITE;  	reg.Offset = CISREG_IOBASE_1;  	reg.Value = (link->io.BasePort2 >> 8) & 0xff; -	if ((err = pcmcia_access_configuration_register(link, ®))) { -	    cs_error(link, AccessConfigurationRegister, err); +	if ((err = pcmcia_access_configuration_register(link, ®)))  	    goto config_error; -	}  	/* There is no config entry for the Ethernet part which  	 * is at 0x0800. So we allocate a window into the attribute @@ -975,17 +923,14 @@ xirc2ps_config(struct pcmcia_device * link)  	req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;  	req.Base = req.Size = 0;  	req.AccessSpeed = 0; -	if ((err = pcmcia_request_window(&link, &req, &link->win))) { -	    cs_error(link, RequestWindow, err); +	if ((err = pcmcia_request_window(link, &req, &link->win)))  	    goto config_error; -	} +  	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;  	mem.CardOffset = 0x0;  	mem.Page = 0; -	if ((err = pcmcia_map_mem_page(link->win, &mem))) { -	    cs_error(link, MapMemPage, err); +	if ((err = pcmcia_map_mem_page(link, link->win, &mem)))  	    goto config_error; -	}  	/* Setup the CCRs; there are no infos in the CIS about the Ethernet  	 * part. @@ -1044,7 +989,7 @@ xirc2ps_config(struct pcmcia_device * link)  	do_reset(dev, 1); /* a kludge to make the cem56 work */      link->dev_node = &local->node; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if ((err=register_netdev(dev))) {  	printk(KNOT_XIRC "register_netdev() failed\n"); @@ -1077,7 +1022,7 @@ xirc2ps_config(struct pcmcia_device * link)  static void  xirc2ps_release(struct pcmcia_device *link)  { -	DEBUG(0, "release(0x%p)\n", link); +	dev_dbg(&link->dev, "release\n");  	if (link->win) {  		struct net_device *dev = link->priv; @@ -1144,7 +1089,7 @@ xirc2ps_interrupt(int irq, void *dev_id)  	PutByte(XIRCREG_CR, 0);      } -    DEBUG(6, "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr); +    pr_debug("%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr);      saved_page = GetByte(XIRCREG_PR);      /* Read the ISR to see whats the cause for the interrupt. @@ -1154,7 +1099,7 @@ xirc2ps_interrupt(int irq, void *dev_id)      bytes_rcvd = 0;    loop_entry:      if (int_status == 0xff) { /* card may be ejected */ -	DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq); +	pr_debug("%s: interrupt %d for dead card\n", dev->name, irq);  	goto leave;      }      eth_status = GetByte(XIRCREG_ESR); @@ -1167,7 +1112,7 @@ xirc2ps_interrupt(int irq, void *dev_id)      PutByte(XIRCREG40_TXST0, 0);      PutByte(XIRCREG40_TXST1, 0); -    DEBUG(3, "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n", +    pr_debug("%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n",  	  dev->name, int_status, eth_status, rx_status, tx_status);      /***** receive section ******/ @@ -1178,14 +1123,14 @@ xirc2ps_interrupt(int irq, void *dev_id)  	    /* too many bytes received during this int, drop the rest of the  	     * packets */  	    dev->stats.rx_dropped++; -	    DEBUG(2, "%s: RX drop, too much done\n", dev->name); +	    pr_debug("%s: RX drop, too much done\n", dev->name);  	} else if (rsr & PktRxOk) {  	    struct sk_buff *skb;  	    pktlen = GetWord(XIRCREG0_RBC);  	    bytes_rcvd += pktlen; -	    DEBUG(5, "rsr=%#02x packet_length=%u\n", rsr, pktlen); +	    pr_debug("rsr=%#02x packet_length=%u\n", rsr, pktlen);  	    skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */  	    if (!skb) { @@ -1253,19 +1198,19 @@ xirc2ps_interrupt(int irq, void *dev_id)  		    dev->stats.multicast++;  	    }  	} else { /* bad packet */ -	    DEBUG(5, "rsr=%#02x\n", rsr); +	    pr_debug("rsr=%#02x\n", rsr);  	}  	if (rsr & PktTooLong) {  	    dev->stats.rx_frame_errors++; -	    DEBUG(3, "%s: Packet too long\n", dev->name); +	    pr_debug("%s: Packet too long\n", dev->name);  	}  	if (rsr & CRCErr) {  	    dev->stats.rx_crc_errors++; -	    DEBUG(3, "%s: CRC error\n", dev->name); +	    pr_debug("%s: CRC error\n", dev->name);  	}  	if (rsr & AlignErr) {  	    dev->stats.rx_fifo_errors++; /* okay ? */ -	    DEBUG(3, "%s: Alignment error\n", dev->name); +	    pr_debug("%s: Alignment error\n", dev->name);  	}  	/* clear the received/dropped/error packet */ @@ -1277,7 +1222,7 @@ xirc2ps_interrupt(int irq, void *dev_id)      if (rx_status & 0x10) { /* Receive overrun */  	dev->stats.rx_over_errors++;  	PutByte(XIRCREG_CR, ClearRxOvrun); -	DEBUG(3, "receive overrun cleared\n"); +	pr_debug("receive overrun cleared\n");      }      /***** transmit section ******/ @@ -1290,13 +1235,13 @@ xirc2ps_interrupt(int irq, void *dev_id)  	if (nn < n) /* rollover */  	    dev->stats.tx_packets += 256 - n;  	else if (n == nn) { /* happens sometimes - don't know why */ -	    DEBUG(0, "PTR not changed?\n"); +	    pr_debug("PTR not changed?\n");  	} else  	    dev->stats.tx_packets += lp->last_ptr_value - n;  	netif_wake_queue(dev);      }      if (tx_status & 0x0002) {	/* Execessive collissions */ -	DEBUG(0, "tx restarted due to execssive collissions\n"); +	pr_debug("tx restarted due to execssive collissions\n");  	PutByte(XIRCREG_CR, RestartTx);  /* restart transmitter process */      }      if (tx_status & 0x0040) @@ -1315,14 +1260,14 @@ xirc2ps_interrupt(int irq, void *dev_id)  		maxrx_bytes = 2000;  	    else if (maxrx_bytes > 22000)  		maxrx_bytes = 22000; -	    DEBUG(1, "set maxrx=%u (rcvd=%u ticks=%lu)\n", +	    pr_debug("set maxrx=%u (rcvd=%u ticks=%lu)\n",  		  maxrx_bytes, bytes_rcvd, duration);  	} else if (!duration && maxrx_bytes < 22000) {  	    /* now much faster */  	    maxrx_bytes += 2000;  	    if (maxrx_bytes > 22000)  		maxrx_bytes = 22000; -	    DEBUG(1, "set maxrx=%u\n", maxrx_bytes); +	    pr_debug("set maxrx=%u\n", maxrx_bytes);  	}      } @@ -1372,7 +1317,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)      unsigned freespace;      unsigned pktlen = skb->len; -    DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n", +    pr_debug("do_start_xmit(skb=%p, dev=%p) len=%u\n",  	  skb, dev, pktlen); @@ -1398,7 +1343,7 @@ do_start_xmit(struct sk_buff *skb, struct net_device *dev)      freespace &= 0x7fff;      /* TRS doesn't work - (indeed it is eliminated with sil-rev 1) */      okay = pktlen +2 < freespace; -    DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n", +    pr_debug("%s: avail. tx space=%u%s\n",  	  dev->name, freespace, okay ? " (okay)":" (not enough)");      if (!okay) { /* not enough space */  	return NETDEV_TX_BUSY;  /* upper layer may decide to requeue this packet */ @@ -1500,7 +1445,7 @@ do_config(struct net_device *dev, struct ifmap *map)  {      local_info_t *local = netdev_priv(dev); -    DEBUG(0, "do_config(%p)\n", dev); +    pr_debug("do_config(%p)\n", dev);      if (map->port != 255 && map->port != dev->if_port) {  	if (map->port > 4)  	    return -EINVAL; @@ -1527,7 +1472,7 @@ do_open(struct net_device *dev)      local_info_t *lp = netdev_priv(dev);      struct pcmcia_device *link = lp->p_dev; -    DEBUG(0, "do_open(%p)\n", dev); +    dev_dbg(&link->dev, "do_open(%p)\n", dev);      /* Check that the PCMCIA card is still here. */      /* Physical device present signature. */ @@ -1561,7 +1506,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)      unsigned int ioaddr = dev->base_addr;      struct mii_ioctl_data *data = if_mii(rq); -    DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", +    pr_debug("%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n",  	  dev->name, rq->ifr_ifrn.ifrn_name, cmd,  	  data->phy_id, data->reg_num, data->val_in, data->val_out); @@ -1610,7 +1555,7 @@ do_reset(struct net_device *dev, int full)      unsigned int ioaddr = dev->base_addr;      unsigned value; -    DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full); +    pr_debug("%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full);      hardreset(dev);      PutByte(XIRCREG_CR, SoftReset); /* set */ @@ -1648,8 +1593,8 @@ do_reset(struct net_device *dev, int full)      }      msleep(40);			     /* wait 40 msec to let it complete */ -  #ifdef PCMCIA_DEBUG -    if (pc_debug) { +  #if 0 +    {  	SelectPage(0);  	value = GetByte(XIRCREG_ESR);	 /* read the ESR */  	printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value); @@ -1666,7 +1611,7 @@ do_reset(struct net_device *dev, int full)  	value |= DisableLinkPulse;      PutByte(XIRCREG1_ECR, value);    #endif -    DEBUG(0, "%s: ECR is: %#02x\n", dev->name, value); +    pr_debug("%s: ECR is: %#02x\n", dev->name, value);      SelectPage(0x42);      PutByte(XIRCREG42_SWC0, 0x20); /* disable source insertion */ @@ -1844,7 +1789,7 @@ do_powerdown(struct net_device *dev)      unsigned int ioaddr = dev->base_addr; -    DEBUG(0, "do_powerdown(%p)\n", dev); +    pr_debug("do_powerdown(%p)\n", dev);      SelectPage(4);      PutByte(XIRCREG4_GPR1, 0);	     /* clear bit 0: power down */ @@ -1858,7 +1803,7 @@ do_stop(struct net_device *dev)      local_info_t *lp = netdev_priv(dev);      struct pcmcia_device *link = lp->p_dev; -    DEBUG(0, "do_stop(%p)\n", dev); +    dev_dbg(&link->dev, "do_stop(%p)\n", dev);      if (!link)  	return -ENODEV; diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c index d0593ed9170..f6036fb4231 100644 --- a/drivers/net/wireless/airo_cs.c +++ b/drivers/net/wireless/airo_cs.c @@ -43,21 +43,6 @@  #include "airo.h" -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -static char *version = "$Revision: 1.2 $"; -#define DEBUG(n, args...) if (pc_debug > (n)) printk(KERN_DEBUG args); -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -145,11 +130,10 @@ static int airo_probe(struct pcmcia_device *p_dev)  {  	local_info_t *local; -	DEBUG(0, "airo_attach()\n"); +	dev_dbg(&p_dev->dev, "airo_attach()\n");  	/* Interrupt setup */  	p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;  	p_dev->irq.Handler = NULL;  	/* @@ -184,7 +168,7 @@ static int airo_probe(struct pcmcia_device *p_dev)  static void airo_detach(struct pcmcia_device *link)  { -	DEBUG(0, "airo_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "airo_detach\n");  	airo_release(link); @@ -204,9 +188,6 @@ static void airo_detach(struct pcmcia_device *link)    ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int airo_cs_config_check(struct pcmcia_device *p_dev,  				cistpl_cftable_entry_t *cfg,  				cistpl_cftable_entry_t *dflt, @@ -275,11 +256,11 @@ static int airo_cs_config_check(struct pcmcia_device *p_dev,  		req->Base = mem->win[0].host_addr;  		req->Size = mem->win[0].len;  		req->AccessSpeed = 0; -		if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) +		if (pcmcia_request_window(p_dev, req, &p_dev->win) != 0)  			return -ENODEV;  		map.Page = 0;  		map.CardOffset = mem->win[0].card_addr; -		if (pcmcia_map_mem_page(p_dev->win, &map) != 0) +		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)  			return -ENODEV;  	}  	/* If we got this far, we're cool! */ @@ -291,11 +272,11 @@ static int airo_config(struct pcmcia_device *link)  {  	local_info_t *dev;  	win_req_t *req; -	int last_fn, last_ret; +	int ret;  	dev = link->priv; -	DEBUG(0, "airo_config(0x%p)\n", link); +	dev_dbg(&link->dev, "airo_config\n");  	req = kzalloc(sizeof(win_req_t), GFP_KERNEL);  	if (!req) @@ -315,8 +296,8 @@ static int airo_config(struct pcmcia_device *link)  	 * and most client drivers will only use the CIS to fill in  	 * implementation-defined details.  	 */ -	last_ret = pcmcia_loop_config(link, airo_cs_config_check, req); -	if (last_ret) +	ret = pcmcia_loop_config(link, airo_cs_config_check, req); +	if (ret)  		goto failed;  	/* @@ -324,21 +305,25 @@ static int airo_config(struct pcmcia_device *link)  	  handler to the interrupt, unless the 'Handler' member of the  	  irq structure is initialized.  	*/ -	if (link->conf.Attributes & CONF_ENABLE_IRQ) -		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +	if (link->conf.Attributes & CONF_ENABLE_IRQ) { +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed; +	}  	/*  	  This actually configures the PCMCIA socket -- setting up  	  the I/O windows and the interrupt mapping, and putting the  	  card and host interface into "Memory and IO" mode.  	*/ -	CS_CHECK(RequestConfiguration, -		 pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	((local_info_t *)link->priv)->eth_dev =  		init_airo_card(link->irq.AssignedIRQ, -			       link->io.BasePort1, 1, &handle_to_dev(link)); +			       link->io.BasePort1, 1, &link->dev);  	if (!((local_info_t *)link->priv)->eth_dev) -		goto cs_failed; +		goto failed;  	/*  	  At this point, the dev_node_t structure(s) need to be @@ -368,8 +353,6 @@ static int airo_config(struct pcmcia_device *link)  	kfree(req);  	return 0; - cs_failed: -	cs_error(link, last_fn, last_ret);   failed:  	airo_release(link);  	kfree(req); @@ -386,7 +369,7 @@ static int airo_config(struct pcmcia_device *link)  static void airo_release(struct pcmcia_device *link)  { -	DEBUG(0, "airo_release(0x%p)\n", link); +	dev_dbg(&link->dev, "airo_release\n");  	pcmcia_disable_device(link);  } diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index ddaa859c349..32407911842 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -55,22 +55,6 @@  #include "atmel.h" -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -static char *version = "$Revision: 1.2 $"; -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -155,11 +139,10 @@ static int atmel_probe(struct pcmcia_device *p_dev)  {  	local_info_t *local; -	DEBUG(0, "atmel_attach()\n"); +	dev_dbg(&p_dev->dev, "atmel_attach()\n");  	/* Interrupt setup */  	p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID;  	p_dev->irq.Handler = NULL;  	/* @@ -194,7 +177,7 @@ static int atmel_probe(struct pcmcia_device *p_dev)  static void atmel_detach(struct pcmcia_device *link)  { -	DEBUG(0, "atmel_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "atmel_detach\n");  	atmel_release(link); @@ -209,9 +192,6 @@ static void atmel_detach(struct pcmcia_device *link)    ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  /* Call-back function to interrogate PCMCIA-specific information     about the current existance of the card */  static int card_present(void *arg) @@ -275,13 +255,13 @@ static int atmel_config_check(struct pcmcia_device *p_dev,  static int atmel_config(struct pcmcia_device *link)  {  	local_info_t *dev; -	int last_fn, last_ret; +	int ret;  	struct pcmcia_device_id *did;  	dev = link->priv; -	did = dev_get_drvdata(&handle_to_dev(link)); +	did = dev_get_drvdata(&link->dev); -	DEBUG(0, "atmel_config(0x%p)\n", link); +	dev_dbg(&link->dev, "atmel_config\n");  	/*  	  In this loop, we scan the CIS for configuration table entries, @@ -303,31 +283,36 @@ static int atmel_config(struct pcmcia_device *link)  	  handler to the interrupt, unless the 'Handler' member of the  	  irq structure is initialized.  	*/ -	if (link->conf.Attributes & CONF_ENABLE_IRQ) -		CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +	if (link->conf.Attributes & CONF_ENABLE_IRQ) { +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed; +	}  	/*  	  This actually configures the PCMCIA socket -- setting up  	  the I/O windows and the interrupt mapping, and putting the  	  card and host interface into "Memory and IO" mode.  	*/ -	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	if (link->irq.AssignedIRQ == 0) {  		printk(KERN_ALERT  		       "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config."); -		goto cs_failed; +		goto failed;  	}  	((local_info_t*)link->priv)->eth_dev =  		init_atmel_card(link->irq.AssignedIRQ,  				link->io.BasePort1,  				did ? did->driver_info : ATMEL_FW_TYPE_NONE, -				&handle_to_dev(link), +				&link->dev,  				card_present,  				link);  	if (!((local_info_t*)link->priv)->eth_dev) -			goto cs_failed; +			goto failed;  	/* @@ -340,8 +325,6 @@ static int atmel_config(struct pcmcia_device *link)  	return 0; - cs_failed: -	cs_error(link, last_fn, last_ret);   failed:  	atmel_release(link);  	return -ENODEV; @@ -359,7 +342,7 @@ static void atmel_release(struct pcmcia_device *link)  {  	struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; -	DEBUG(0, "atmel_release(0x%p)\n", link); +	dev_dbg(&link->dev, "atmel_release\n");  	if (dev)  		stop_atmel_card(dev); diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 6c3a74964ab..984174bc7b0 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -65,35 +65,15 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)  	struct ssb_bus *ssb;  	win_req_t win;  	memreq_t mem; -	tuple_t tuple; -	cisparse_t parse;  	int err = -ENOMEM;  	int res = 0; -	unsigned char buf[64];  	ssb = kzalloc(sizeof(*ssb), GFP_KERNEL);  	if (!ssb)  		goto out_error;  	err = -ENODEV; -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; -	res = pcmcia_get_first_tuple(dev, &tuple); -	if (res != 0) -		goto err_kfree_ssb; -	res = pcmcia_get_tuple_data(dev, &tuple); -	if (res != 0) -		goto err_kfree_ssb; -	res = pcmcia_parse_tuple(&tuple, &parse); -	if (res != 0) -		goto err_kfree_ssb; - -	dev->conf.ConfigBase = parse.config.base; -	dev->conf.Present = parse.config.rmask[0];  	dev->conf.Attributes = CONF_ENABLE_IRQ;  	dev->conf.IntType = INT_MEMORY_AND_IO; @@ -107,20 +87,18 @@ static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev)  	win.Base = 0;  	win.Size = SSB_CORE_SIZE;  	win.AccessSpeed = 250; -	res = pcmcia_request_window(&dev, &win, &dev->win); +	res = pcmcia_request_window(dev, &win, &dev->win);  	if (res != 0)  		goto err_kfree_ssb;  	mem.CardOffset = 0;  	mem.Page = 0; -	res = pcmcia_map_mem_page(dev->win, &mem); +	res = pcmcia_map_mem_page(dev, dev->win, &mem);  	if (res != 0)  		goto err_disable;  	dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	dev->irq.IRQInfo1 = IRQ_LEVEL_ID;  	dev->irq.Handler = NULL; /* The handler is registered later. */ -	dev->irq.Instance = NULL;  	res = pcmcia_request_irq(dev, &dev->irq);  	if (res != 0)  		goto err_disable; diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index ad8eab4a639..c9640a3e02c 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -274,9 +274,6 @@ static int sandisk_enable_wireless(struct net_device *dev)  	conf_reg_t reg;  	struct hostap_interface *iface = netdev_priv(dev);  	local_info_t *local = iface->local; -	tuple_t tuple; -	cisparse_t *parse = NULL; -	u_char buf[64];  	struct hostap_cs_priv *hw_priv = local->hw_priv;  	if (hw_priv->link->io.NumPorts1 < 0x42) { @@ -285,28 +282,13 @@ static int sandisk_enable_wireless(struct net_device *dev)  		goto done;  	} -	parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); -	if (parse == NULL) { -		ret = -ENOMEM; -		goto done; -	} - -	tuple.Attributes = TUPLE_RETURN_COMMON; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; -  	if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) {  		/* No SanDisk manfid found */  		ret = -ENODEV;  		goto done;  	} -	tuple.DesiredTuple = CISTPL_LONGLINK_MFC; -	if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || -	    pcmcia_get_tuple_data(hw_priv->link, &tuple) || -	    pcmcia_parse_tuple(&tuple, parse) || -		parse->longlink_mfc.nfn < 2) { +	if (hw_priv->link->socket->functions < 2) {  		/* No multi-function links found */  		ret = -ENODEV;  		goto done; @@ -354,7 +336,6 @@ static int sandisk_enable_wireless(struct net_device *dev)  	udelay(10);  done: -	kfree(parse);  	return ret;  } @@ -529,10 +510,6 @@ static void prism2_detach(struct pcmcia_device *link)  } -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -  /* run after a CARD_INSERTION event is received to configure the PCMCIA   * socket and make the device available to the system */ @@ -624,7 +601,6 @@ static int prism2_config(struct pcmcia_device *link)  	struct hostap_interface *iface;  	local_info_t *local;  	int ret = 1; -	int last_fn, last_ret;  	struct hostap_cs_priv *hw_priv;  	PDEBUG(DEBUG_FLOW, "prism2_config()\n"); @@ -636,19 +612,18 @@ static int prism2_config(struct pcmcia_device *link)  	}  	/* Look for an appropriate configuration table entry in the CIS */ -	last_ret = pcmcia_loop_config(link, prism2_config_check, NULL); -	if (last_ret) { +	ret = pcmcia_loop_config(link, prism2_config_check, NULL); +	if (ret) {  		if (!ignore_cis_vcc)  			printk(KERN_ERR "GetNextTuple(): No matching "  			       "CIS configuration.  Maybe you need the "  			       "ignore_cis_vcc=1 parameter.\n"); -		cs_error(link, RequestIO, last_ret);  		goto failed;  	}  	/* Need to allocate net_device before requesting IRQ handler */  	dev = prism2_init_local_data(&prism2_pccard_funcs, 0, -				     &handle_to_dev(link)); +				     &link->dev);  	if (dev == NULL)  		goto failed;  	link->priv = dev; @@ -666,13 +641,11 @@ static int prism2_config(struct pcmcia_device *link)  	 * irq structure is initialized.  	 */  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | -				       IRQ_HANDLE_PRESENT; -		link->irq.IRQInfo1 = IRQ_LEVEL_ID; +		link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  		link->irq.Handler = prism2_interrupt; -		link->irq.Instance = dev; -		CS_CHECK(RequestIRQ, -			 pcmcia_request_irq(link, &link->irq)); +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/* @@ -680,8 +653,9 @@ static int prism2_config(struct pcmcia_device *link)  	 * the I/O windows and the interrupt mapping, and putting the  	 * card and host interface into "Memory and IO" mode.  	 */ -	CS_CHECK(RequestConfiguration, -		 pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	dev->irq = link->irq.AssignedIRQ;  	dev->base_addr = link->io.BasePort1; @@ -714,9 +688,6 @@ static int prism2_config(struct pcmcia_device *link)  	}  	return ret; - cs_failed: -	cs_error(link, last_fn, last_ret); -   failed:  	kfree(hw_priv);  	prism2_release((u_long)link); diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 875516db319..1f6cb58dd66 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -591,7 +591,7 @@ static int if_cs_prog_helper(struct if_cs_card *card)  	/* TODO: make firmware file configurable */  	ret = request_firmware(&fw, "libertas_cs_helper.fw", -		&handle_to_dev(card->p_dev)); +		&card->p_dev->dev);  	if (ret) {  		lbs_pr_err("can't load helper firmware\n");  		ret = -ENODEV; @@ -664,7 +664,7 @@ static int if_cs_prog_real(struct if_cs_card *card)  	/* TODO: make firmware file configurable */  	ret = request_firmware(&fw, "libertas_cs.fw", -		&handle_to_dev(card->p_dev)); +		&card->p_dev->dev);  	if (ret) {  		lbs_pr_err("can't load firmware\n");  		ret = -ENODEV; @@ -794,18 +794,37 @@ static void if_cs_release(struct pcmcia_device *p_dev)   * configure the card at this point -- we wait until we receive a card   * insertion event.   */ + +static int if_cs_ioprobe(struct pcmcia_device *p_dev, +			 cistpl_cftable_entry_t *cfg, +			 cistpl_cftable_entry_t *dflt, +			 unsigned int vcc, +			 void *priv_data) +{ +	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +	p_dev->io.BasePort1 = cfg->io.win[0].base; +	p_dev->io.NumPorts1 = cfg->io.win[0].len; + +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; + +	/* IO window settings */ +	if (cfg->io.nwin != 1) { +		lbs_pr_err("wrong CIS (check number of IO windows)\n"); +		return -ENODEV; +	} + +	/* This reserves IO space but doesn't actually enable it */ +	return pcmcia_request_io(p_dev, &p_dev->io); +} +  static int if_cs_probe(struct pcmcia_device *p_dev)  {  	int ret = -ENOMEM;  	unsigned int prod_id;  	struct lbs_private *priv;  	struct if_cs_card *card; -	/* CIS parsing */ -	tuple_t tuple; -	cisparse_t parse; -	cistpl_cftable_entry_t *cfg = &parse.cftable_entry; -	cistpl_io_t *io = &cfg->io; -	u_char buf[64];  	lbs_deb_enter(LBS_DEB_CS); @@ -819,48 +838,15 @@ static int if_cs_probe(struct pcmcia_device *p_dev)  	p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	p_dev->irq.Handler = NULL; -	p_dev->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;  	p_dev->conf.Attributes = 0;  	p_dev->conf.IntType = INT_MEMORY_AND_IO; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 || -	    (ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 || -	    (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) -	{ -		lbs_pr_err("error in pcmcia_get_first_tuple etc\n"); +	if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { +		lbs_pr_err("error in pcmcia_loop_config\n");  		goto out1;  	} -	p_dev->conf.ConfigIndex = cfg->index; - -	/* Do we need to allocate an interrupt? */ -	if (cfg->irq.IRQInfo1) { -		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; -	} - -	/* IO window settings */ -	if (cfg->io.nwin != 1) { -		lbs_pr_err("wrong CIS (check number of IO windows)\n"); -		ret = -ENODEV; -		goto out1; -	} -	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -	p_dev->io.BasePort1 = io->win[0].base; -	p_dev->io.NumPorts1 = io->win[0].len; - -	/* This reserves IO space but doesn't actually enable it */ -	ret = pcmcia_request_io(p_dev, &p_dev->io); -	if (ret) { -		lbs_pr_err("error in pcmcia_request_io\n"); -		goto out1; -	}  	/*  	 * Allocate an interrupt line.  Note that this does not assign diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c index 38c1c9d2abb..f27bb8367c9 100644 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/orinoco/orinoco_cs.c @@ -109,7 +109,7 @@ orinoco_cs_probe(struct pcmcia_device *link)  	struct orinoco_private *priv;  	struct orinoco_pccard *card; -	priv = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), +	priv = alloc_orinocodev(sizeof(*card), &link->dev,  				orinoco_cs_hard_reset, NULL);  	if (!priv)  		return -ENOMEM; @@ -120,10 +120,8 @@ orinoco_cs_probe(struct pcmcia_device *link)  	link->priv = priv;  	/* Interrupt setup */ -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = orinoco_interrupt; -	link->irq.Instance = priv;  	/* General socket configuration defaults can go here.  In this  	 * client, we assume very little, and rely on the CIS for @@ -160,12 +158,6 @@ static void orinoco_cs_detach(struct pcmcia_device *link)   * device available to the system.   */ -#define CS_CHECK(fn, ret) do { \ -	last_fn = (fn); \ -	if ((last_ret = (ret)) != 0) \ -		goto cs_failed; \ -} while (0) -  static int orinoco_cs_config_check(struct pcmcia_device *p_dev,  				   cistpl_cftable_entry_t *cfg,  				   cistpl_cftable_entry_t *dflt, @@ -240,7 +232,7 @@ orinoco_cs_config(struct pcmcia_device *link)  	struct orinoco_private *priv = link->priv;  	struct orinoco_pccard *card = priv->card;  	hermes_t *hw = &priv->hw; -	int last_fn, last_ret; +	int ret;  	void __iomem *mem;  	/* @@ -257,13 +249,12 @@ orinoco_cs_config(struct pcmcia_device *link)  	 * and most client drivers will only use the CIS to fill in  	 * implementation-defined details.  	 */ -	last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); -	if (last_ret) { +	ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); +	if (ret) {  		if (!ignore_cis_vcc)  			printk(KERN_ERR PFX "GetNextTuple(): No matching "  			       "CIS configuration.  Maybe you need the "  			       "ignore_cis_vcc=1 parameter.\n"); -		cs_error(link, RequestIO, last_ret);  		goto failed;  	} @@ -272,14 +263,16 @@ orinoco_cs_config(struct pcmcia_device *link)  	 * a handler to the interrupt, unless the 'Handler' member of  	 * the irq structure is initialized.  	 */ -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret) +		goto failed;  	/* We initialize the hermes structure before completing PCMCIA  	 * configuration just in case the interrupt handler gets  	 * called. */  	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);  	if (!mem) -		goto cs_failed; +		goto failed;  	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); @@ -288,8 +281,9 @@ orinoco_cs_config(struct pcmcia_device *link)  	 * the I/O windows and the interrupt mapping, and putting the  	 * card and host interface into "Memory and IO" mode.  	 */ -	CS_CHECK(RequestConfiguration, -		 pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/* Ok, we have the configuration, prepare to register the netdev */  	card->node.major = card->node.minor = 0; @@ -315,9 +309,6 @@ orinoco_cs_config(struct pcmcia_device *link)  				       * net_device has been registered */  	return 0; - cs_failed: -	cs_error(link, last_fn, last_ret); -   failed:  	orinoco_cs_release(link);  	return -ENODEV; diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c index c361310b885..59bda240fdc 100644 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/orinoco/spectrum_cs.c @@ -73,9 +73,6 @@ static void spectrum_cs_release(struct pcmcia_device *link);  #define HCR_MEM16	0x10	/* memory width bit, should be preserved */ -#define CS_CHECK(fn, ret) \ -  do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  /*   * Reset the card using configuration registers COR and CCSR.   * If IDLE is 1, stop the firmware, so that it can be safely rewritten. @@ -83,7 +80,7 @@ static void spectrum_cs_release(struct pcmcia_device *link);  static int  spectrum_reset(struct pcmcia_device *link, int idle)  { -	int last_ret, last_fn; +	int ret;  	conf_reg_t reg;  	u_int save_cor; @@ -95,23 +92,26 @@ spectrum_reset(struct pcmcia_device *link, int idle)  	reg.Function = 0;  	reg.Action = CS_READ;  	reg.Offset = CISREG_COR; -	CS_CHECK(AccessConfigurationRegister, -		 pcmcia_access_configuration_register(link, ®)); +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed;  	save_cor = reg.Value;  	/* Soft-Reset card */  	reg.Action = CS_WRITE;  	reg.Offset = CISREG_COR;  	reg.Value = (save_cor | COR_SOFT_RESET); -	CS_CHECK(AccessConfigurationRegister, -		 pcmcia_access_configuration_register(link, ®)); +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed;  	udelay(1000);  	/* Read CCSR */  	reg.Action = CS_READ;  	reg.Offset = CISREG_CCSR; -	CS_CHECK(AccessConfigurationRegister, -		 pcmcia_access_configuration_register(link, ®)); +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed;  	/*  	 * Start or stop the firmware.  Memory width bit should be @@ -120,21 +120,22 @@ spectrum_reset(struct pcmcia_device *link, int idle)  	reg.Action = CS_WRITE;  	reg.Offset = CISREG_CCSR;  	reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); -	CS_CHECK(AccessConfigurationRegister, -		 pcmcia_access_configuration_register(link, ®)); +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed;  	udelay(1000);  	/* Restore original COR configuration index */  	reg.Action = CS_WRITE;  	reg.Offset = CISREG_COR;  	reg.Value = (save_cor & ~COR_SOFT_RESET); -	CS_CHECK(AccessConfigurationRegister, -		 pcmcia_access_configuration_register(link, ®)); +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed;  	udelay(1000);  	return 0; -cs_failed: -	cs_error(link, last_fn, last_ret); +failed:  	return -ENODEV;  } @@ -181,7 +182,7 @@ spectrum_cs_probe(struct pcmcia_device *link)  	struct orinoco_private *priv;  	struct orinoco_pccard *card; -	priv = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), +	priv = alloc_orinocodev(sizeof(*card), &link->dev,  				spectrum_cs_hard_reset,  				spectrum_cs_stop_firmware);  	if (!priv) @@ -193,10 +194,8 @@ spectrum_cs_probe(struct pcmcia_device *link)  	link->priv = priv;  	/* Interrupt setup */ -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = orinoco_interrupt; -	link->irq.Instance = priv;  	/* General socket configuration defaults can go here.  In this  	 * client, we assume very little, and rely on the CIS for @@ -307,7 +306,7 @@ spectrum_cs_config(struct pcmcia_device *link)  	struct orinoco_private *priv = link->priv;  	struct orinoco_pccard *card = priv->card;  	hermes_t *hw = &priv->hw; -	int last_fn, last_ret; +	int ret;  	void __iomem *mem;  	/* @@ -324,13 +323,12 @@ spectrum_cs_config(struct pcmcia_device *link)  	 * and most client drivers will only use the CIS to fill in  	 * implementation-defined details.  	 */ -	last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); -	if (last_ret) { +	ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); +	if (ret) {  		if (!ignore_cis_vcc)  			printk(KERN_ERR PFX "GetNextTuple(): No matching "  			       "CIS configuration.  Maybe you need the "  			       "ignore_cis_vcc=1 parameter.\n"); -		cs_error(link, RequestIO, last_ret);  		goto failed;  	} @@ -339,14 +337,16 @@ spectrum_cs_config(struct pcmcia_device *link)  	 * a handler to the interrupt, unless the 'Handler' member of  	 * the irq structure is initialized.  	 */ -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret) +		goto failed;  	/* We initialize the hermes structure before completing PCMCIA  	 * configuration just in case the interrupt handler gets  	 * called. */  	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);  	if (!mem) -		goto cs_failed; +		goto failed;  	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); @@ -355,8 +355,9 @@ spectrum_cs_config(struct pcmcia_device *link)  	 * the I/O windows and the interrupt mapping, and putting the  	 * card and host interface into "Memory and IO" mode.  	 */ -	CS_CHECK(RequestConfiguration, -		 pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/* Ok, we have the configuration, prepare to register the netdev */  	card->node.major = card->node.minor = 0; @@ -386,9 +387,6 @@ spectrum_cs_config(struct pcmcia_device *link)  				       * net_device has been registered */  	return 0; - cs_failed: -	cs_error(link, last_fn, last_ret); -   failed:  	spectrum_cs_release(link);  	return -ENODEV; diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index 0366f5aeb91..88e1e4e32b2 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -71,25 +71,7 @@ typedef u_char mac_addr[ETH_ALEN];	/* Hardware address */  #include "rayctl.h"  #include "ray_cs.h" -/* All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef RAYLINK_DEBUG -#define PCMCIA_DEBUG RAYLINK_DEBUG -#endif -#ifdef PCMCIA_DEBUG -static int ray_debug; -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -/* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */ -#define DEBUG(n, args...) if (pc_debug > (n)) printk(args); -#else -#define DEBUG(n, args...) -#endif  /** Prototypes based on PCMCIA skeleton driver *******************************/  static int ray_config(struct pcmcia_device *link);  static void ray_release(struct pcmcia_device *link); @@ -325,7 +307,7 @@ static int ray_probe(struct pcmcia_device *p_dev)  	ray_dev_t *local;  	struct net_device *dev; -	DEBUG(1, "ray_attach()\n"); +	dev_dbg(&p_dev->dev, "ray_attach()\n");  	/* Allocate space for private device-specific data */  	dev = alloc_etherdev(sizeof(ray_dev_t)); @@ -341,8 +323,7 @@ static int ray_probe(struct pcmcia_device *p_dev)  	p_dev->io.IOAddrLines = 5;  	/* Interrupt setup. For PCMCIA, driver takes what's given */ -	p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; +	p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	p_dev->irq.Handler = &ray_interrupt;  	/* General socket configuration */ @@ -351,13 +332,12 @@ static int ray_probe(struct pcmcia_device *p_dev)  	p_dev->conf.ConfigIndex = 1;  	p_dev->priv = dev; -	p_dev->irq.Instance = dev;  	local->finder = p_dev;  	local->card_status = CARD_INSERTED;  	local->authentication_state = UNAUTHENTICATED;  	local->num_multi = 0; -	DEBUG(2, "ray_attach p_dev = %p,  dev = %p,  local = %p, intr = %p\n", +	dev_dbg(&p_dev->dev, "ray_attach p_dev = %p,  dev = %p,  local = %p, intr = %p\n",  	      p_dev, dev, local, &ray_interrupt);  	/* Raylink entries in the device structure */ @@ -370,7 +350,7 @@ static int ray_probe(struct pcmcia_device *p_dev)  #endif /* WIRELESS_SPY */ -	DEBUG(2, "ray_cs ray_attach calling ether_setup.)\n"); +	dev_dbg(&p_dev->dev, "ray_cs ray_attach calling ether_setup.)\n");  	netif_stop_queue(dev);  	init_timer(&local->timer); @@ -393,7 +373,7 @@ static void ray_detach(struct pcmcia_device *link)  	struct net_device *dev;  	ray_dev_t *local; -	DEBUG(1, "ray_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "ray_detach\n");  	this_device = NULL;  	dev = link->priv; @@ -408,7 +388,7 @@ static void ray_detach(struct pcmcia_device *link)  			unregister_netdev(dev);  		free_netdev(dev);  	} -	DEBUG(2, "ray_cs ray_detach ending\n"); +	dev_dbg(&link->dev, "ray_cs ray_detach ending\n");  } /* ray_detach */  /*============================================================================= @@ -416,19 +396,17 @@ static void ray_detach(struct pcmcia_device *link)      is received, to configure the PCMCIA socket, and to make the      ethernet device available to the system.  =============================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)  #define MAX_TUPLE_SIZE 128  static int ray_config(struct pcmcia_device *link)  { -	int last_fn = 0, last_ret = 0; +	int ret = 0;  	int i;  	win_req_t req;  	memreq_t mem;  	struct net_device *dev = (struct net_device *)link->priv;  	ray_dev_t *local = netdev_priv(dev); -	DEBUG(1, "ray_config(0x%p)\n", link); +	dev_dbg(&link->dev, "ray_config\n");  	/* Determine card type and firmware version */  	printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", @@ -440,14 +418,17 @@ static int ray_config(struct pcmcia_device *link)  	/* Now allocate an interrupt line.  Note that this does not  	   actually assign a handler to the interrupt.  	 */ -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret) +		goto failed;  	dev->irq = link->irq.AssignedIRQ;  	/* This actually configures the PCMCIA socket -- setting up  	   the I/O windows and the interrupt mapping.  	 */ -	CS_CHECK(RequestConfiguration, -		 pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  /*** Set up 32k window for shared memory (transmit and control) ************/  	req.Attributes = @@ -455,10 +436,14 @@ static int ray_config(struct pcmcia_device *link)  	req.Base = 0;  	req.Size = 0x8000;  	req.AccessSpeed = ray_mem_speed; -	CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); +	ret = pcmcia_request_window(link, &req, &link->win); +	if (ret) +		goto failed;  	mem.CardOffset = 0x0000;  	mem.Page = 0; -	CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); +	ret = pcmcia_map_mem_page(link, link->win, &mem); +	if (ret) +		goto failed;  	local->sram = ioremap(req.Base, req.Size);  /*** Set up 16k window for shared memory (receive buffer) ***************/ @@ -467,11 +452,14 @@ static int ray_config(struct pcmcia_device *link)  	req.Base = 0;  	req.Size = 0x4000;  	req.AccessSpeed = ray_mem_speed; -	CS_CHECK(RequestWindow, -		 pcmcia_request_window(&link, &req, &local->rmem_handle)); +	ret = pcmcia_request_window(link, &req, &local->rmem_handle); +	if (ret) +		goto failed;  	mem.CardOffset = 0x8000;  	mem.Page = 0; -	CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); +	ret = pcmcia_map_mem_page(link, local->rmem_handle, &mem); +	if (ret) +		goto failed;  	local->rmem = ioremap(req.Base, req.Size);  /*** Set up window for attribute memory ***********************************/ @@ -480,22 +468,25 @@ static int ray_config(struct pcmcia_device *link)  	req.Base = 0;  	req.Size = 0x1000;  	req.AccessSpeed = ray_mem_speed; -	CS_CHECK(RequestWindow, -		 pcmcia_request_window(&link, &req, &local->amem_handle)); +	ret = pcmcia_request_window(link, &req, &local->amem_handle); +	if (ret) +		goto failed;  	mem.CardOffset = 0x0000;  	mem.Page = 0; -	CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); +	ret = pcmcia_map_mem_page(link, local->amem_handle, &mem); +	if (ret) +		goto failed;  	local->amem = ioremap(req.Base, req.Size); -	DEBUG(3, "ray_config sram=%p\n", local->sram); -	DEBUG(3, "ray_config rmem=%p\n", local->rmem); -	DEBUG(3, "ray_config amem=%p\n", local->amem); +	dev_dbg(&link->dev, "ray_config sram=%p\n", local->sram); +	dev_dbg(&link->dev, "ray_config rmem=%p\n", local->rmem); +	dev_dbg(&link->dev, "ray_config amem=%p\n", local->amem);  	if (ray_init(dev) < 0) {  		ray_release(link);  		return -ENODEV;  	} -	SET_NETDEV_DEV(dev, &handle_to_dev(link)); +	SET_NETDEV_DEV(dev, &link->dev);  	i = register_netdev(dev);  	if (i != 0) {  		printk("ray_config register_netdev() failed\n"); @@ -511,9 +502,7 @@ static int ray_config(struct pcmcia_device *link)  	return 0; -cs_failed: -	cs_error(link, last_fn, last_ret); - +failed:  	ray_release(link);  	return -ENODEV;  } /* ray_config */ @@ -543,9 +532,9 @@ static int ray_init(struct net_device *dev)  	struct ccs __iomem *pccs;  	ray_dev_t *local = netdev_priv(dev);  	struct pcmcia_device *link = local->finder; -	DEBUG(1, "ray_init(0x%p)\n", dev); +	dev_dbg(&link->dev, "ray_init(0x%p)\n", dev);  	if (!(pcmcia_dev_present(link))) { -		DEBUG(0, "ray_init - device not present\n"); +		dev_dbg(&link->dev, "ray_init - device not present\n");  		return -1;  	} @@ -567,13 +556,13 @@ static int ray_init(struct net_device *dev)  	local->fw_ver = local->startup_res.firmware_version[0];  	local->fw_bld = local->startup_res.firmware_version[1];  	local->fw_var = local->startup_res.firmware_version[2]; -	DEBUG(1, "ray_init firmware version %d.%d \n", local->fw_ver, +	dev_dbg(&link->dev, "ray_init firmware version %d.%d \n", local->fw_ver,  	      local->fw_bld);  	local->tib_length = 0x20;  	if ((local->fw_ver == 5) && (local->fw_bld >= 30))  		local->tib_length = local->startup_res.tib_length; -	DEBUG(2, "ray_init tib_length = 0x%02x\n", local->tib_length); +	dev_dbg(&link->dev, "ray_init tib_length = 0x%02x\n", local->tib_length);  	/* Initialize CCS's to buffer free state */  	pccs = ccs_base(local);  	for (i = 0; i < NUMBER_OF_CCS; i++) { @@ -592,7 +581,7 @@ static int ray_init(struct net_device *dev)  	clear_interrupt(local);	/* Clear any interrupt from the card */  	local->card_status = CARD_AWAITING_PARAM; -	DEBUG(2, "ray_init ending\n"); +	dev_dbg(&link->dev, "ray_init ending\n");  	return 0;  } /* ray_init */ @@ -605,9 +594,9 @@ static int dl_startup_params(struct net_device *dev)  	struct ccs __iomem *pccs;  	struct pcmcia_device *link = local->finder; -	DEBUG(1, "dl_startup_params entered\n"); +	dev_dbg(&link->dev, "dl_startup_params entered\n");  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs dl_startup_params - device not present\n"); +		dev_dbg(&link->dev, "ray_cs dl_startup_params - device not present\n");  		return -1;  	} @@ -625,7 +614,7 @@ static int dl_startup_params(struct net_device *dev)  	local->dl_param_ccs = ccsindex;  	pccs = ccs_base(local) + ccsindex;  	writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); -	DEBUG(2, "dl_startup_params start ccsindex = %d\n", +	dev_dbg(&link->dev, "dl_startup_params start ccsindex = %d\n",  	      local->dl_param_ccs);  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { @@ -641,7 +630,7 @@ static int dl_startup_params(struct net_device *dev)  	local->timer.data = (long)local;  	local->timer.function = &verify_dl_startup;  	add_timer(&local->timer); -	DEBUG(2, +	dev_dbg(&link->dev,  	      "ray_cs dl_startup_params started timer for verify_dl_startup\n");  	return 0;  } /* dl_startup_params */ @@ -717,11 +706,11 @@ static void verify_dl_startup(u_long data)  	struct pcmcia_device *link = local->finder;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs verify_dl_startup - device not present\n"); +		dev_dbg(&link->dev, "ray_cs verify_dl_startup - device not present\n");  		return;  	} -#ifdef PCMCIA_DEBUG -	if (pc_debug > 2) { +#if 0 +	{  		int i;  		printk(KERN_DEBUG  		       "verify_dl_startup parameters sent via ccs %d:\n", @@ -760,7 +749,7 @@ static void start_net(u_long data)  	int ccsindex;  	struct pcmcia_device *link = local->finder;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs start_net - device not present\n"); +		dev_dbg(&link->dev, "ray_cs start_net - device not present\n");  		return;  	}  	/* Fill in the CCS fields for the ECF */ @@ -771,7 +760,7 @@ static void start_net(u_long data)  	writeb(0, &pccs->var.start_network.update_param);  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(1, "ray start net failed - card not ready for intr\n"); +		dev_dbg(&link->dev, "ray start net failed - card not ready for intr\n");  		writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);  		return;  	} @@ -790,7 +779,7 @@ static void join_net(u_long data)  	struct pcmcia_device *link = local->finder;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs join_net - device not present\n"); +		dev_dbg(&link->dev, "ray_cs join_net - device not present\n");  		return;  	}  	/* Fill in the CCS fields for the ECF */ @@ -802,7 +791,7 @@ static void join_net(u_long data)  	writeb(0, &pccs->var.join_network.net_initiated);  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(1, "ray join net failed - card not ready for intr\n"); +		dev_dbg(&link->dev, "ray join net failed - card not ready for intr\n");  		writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);  		return;  	} @@ -821,7 +810,7 @@ static void ray_release(struct pcmcia_device *link)  	ray_dev_t *local = netdev_priv(dev);  	int i; -	DEBUG(1, "ray_release(0x%p)\n", link); +	dev_dbg(&link->dev, "ray_release\n");  	del_timer(&local->timer); @@ -829,15 +818,15 @@ static void ray_release(struct pcmcia_device *link)  	iounmap(local->rmem);  	iounmap(local->amem);  	/* Do bother checking to see if these succeed or not */ -	i = pcmcia_release_window(local->amem_handle); +	i = pcmcia_release_window(link, local->amem_handle);  	if (i != 0) -		DEBUG(0, "ReleaseWindow(local->amem) ret = %x\n", i); -	i = pcmcia_release_window(local->rmem_handle); +		dev_dbg(&link->dev, "ReleaseWindow(local->amem) ret = %x\n", i); +	i = pcmcia_release_window(link, local->rmem_handle);  	if (i != 0) -		DEBUG(0, "ReleaseWindow(local->rmem) ret = %x\n", i); +		dev_dbg(&link->dev, "ReleaseWindow(local->rmem) ret = %x\n", i);  	pcmcia_disable_device(link); -	DEBUG(2, "ray_release ending\n"); +	dev_dbg(&link->dev, "ray_release ending\n");  }  static int ray_suspend(struct pcmcia_device *link) @@ -871,9 +860,9 @@ static int ray_dev_init(struct net_device *dev)  	ray_dev_t *local = netdev_priv(dev);  	struct pcmcia_device *link = local->finder; -	DEBUG(1, "ray_dev_init(dev=%p)\n", dev); +	dev_dbg(&link->dev, "ray_dev_init(dev=%p)\n", dev);  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_dev_init - device not present\n"); +		dev_dbg(&link->dev, "ray_dev_init - device not present\n");  		return -1;  	}  #ifdef RAY_IMMEDIATE_INIT @@ -887,7 +876,7 @@ static int ray_dev_init(struct net_device *dev)  	/* Postpone the card init so that we can still configure the card,  	 * for example using the Wireless Extensions. The init will happen  	 * in ray_open() - Jean II */ -	DEBUG(1, +	dev_dbg(&link->dev,  	      "ray_dev_init: postponing card init to ray_open() ; Status = %d\n",  	      local->card_status);  #endif /* RAY_IMMEDIATE_INIT */ @@ -896,7 +885,7 @@ static int ray_dev_init(struct net_device *dev)  	memcpy(dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN);  	memset(dev->broadcast, 0xff, ETH_ALEN); -	DEBUG(2, "ray_dev_init ending\n"); +	dev_dbg(&link->dev, "ray_dev_init ending\n");  	return 0;  } @@ -906,9 +895,9 @@ static int ray_dev_config(struct net_device *dev, struct ifmap *map)  	ray_dev_t *local = netdev_priv(dev);  	struct pcmcia_device *link = local->finder;  	/* Dummy routine to satisfy device structure */ -	DEBUG(1, "ray_dev_config(dev=%p,ifmap=%p)\n", dev, map); +	dev_dbg(&link->dev, "ray_dev_config(dev=%p,ifmap=%p)\n", dev, map);  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_dev_config - device not present\n"); +		dev_dbg(&link->dev, "ray_dev_config - device not present\n");  		return -1;  	} @@ -924,14 +913,14 @@ static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb,  	short length = skb->len;  	if (!pcmcia_dev_present(link)) { -		DEBUG(2, "ray_dev_start_xmit - device not present\n"); +		dev_dbg(&link->dev, "ray_dev_start_xmit - device not present\n");  		dev_kfree_skb(skb);  		return NETDEV_TX_OK;  	} -	DEBUG(3, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev); +	dev_dbg(&link->dev, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev);  	if (local->authentication_state == NEED_TO_AUTH) { -		DEBUG(0, "ray_cs Sending authentication request.\n"); +		dev_dbg(&link->dev, "ray_cs Sending authentication request.\n");  		if (!build_auth_frame(local, local->auth_id, OPEN_AUTH_REQUEST)) {  			local->authentication_state = AUTHENTICATED;  			netif_stop_queue(dev); @@ -971,7 +960,7 @@ static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev,  	struct tx_msg __iomem *ptx;	/* Address of xmit buffer in PC space */  	short int addr;		/* Address of xmit buffer in card space */ -	DEBUG(3, "ray_hw_xmit(data=%p, len=%d, dev=%p)\n", data, len, dev); +	pr_debug("ray_hw_xmit(data=%p, len=%d, dev=%p)\n", data, len, dev);  	if (len + TX_HEADER_LENGTH > TX_BUF_SIZE) {  		printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n",  		       len); @@ -979,9 +968,9 @@ static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev,  	}  	switch (ccsindex = get_free_tx_ccs(local)) {  	case ECCSBUSY: -		DEBUG(2, "ray_hw_xmit tx_ccs table busy\n"); +		pr_debug("ray_hw_xmit tx_ccs table busy\n");  	case ECCSFULL: -		DEBUG(2, "ray_hw_xmit No free tx ccs\n"); +		pr_debug("ray_hw_xmit No free tx ccs\n");  	case ECARDGONE:  		netif_stop_queue(dev);  		return XMIT_NO_CCS; @@ -1018,12 +1007,12 @@ static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev,  	writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode);  	writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate);  	writeb(0, &pccs->var.tx_request.antenna); -	DEBUG(3, "ray_hw_xmit default_tx_rate = 0x%x\n", +	pr_debug("ray_hw_xmit default_tx_rate = 0x%x\n",  	      local->net_default_tx_rate);  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(2, "ray_hw_xmit failed - ECF not ready for intr\n"); +		pr_debug("ray_hw_xmit failed - ECF not ready for intr\n");  /* TBD very inefficient to copy packet to buffer, and then not     send it, but the alternative is to queue the messages and that     won't be done for a while.  Maybe set tbusy until a CCS is free? @@ -1040,7 +1029,7 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,  {  	__be16 proto = ((struct ethhdr *)data)->h_proto;  	if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ -		DEBUG(3, "ray_cs translate_frame DIX II\n"); +		pr_debug("ray_cs translate_frame DIX II\n");  		/* Copy LLC header to card buffer */  		memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));  		memcpy_toio(((void __iomem *)&ptx->var) + sizeof(eth2_llc), @@ -1056,9 +1045,9 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,  			    len - ETH_HLEN);  		return (int)sizeof(struct snaphdr_t) - ETH_HLEN;  	} else { /* already  802 type, and proto is length */ -		DEBUG(3, "ray_cs translate_frame 802\n"); +		pr_debug("ray_cs translate_frame 802\n");  		if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */ -			DEBUG(3, "ray_cs translate_frame evil IPX\n"); +			pr_debug("ray_cs translate_frame evil IPX\n");  			memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN);  			return 0 - ETH_HLEN;  		} @@ -1603,7 +1592,7 @@ static int ray_open(struct net_device *dev)  	struct pcmcia_device *link;  	link = local->finder; -	DEBUG(1, "ray_open('%s')\n", dev->name); +	dev_dbg(&link->dev, "ray_open('%s')\n", dev->name);  	if (link->open == 0)  		local->num_multi = 0; @@ -1613,7 +1602,7 @@ static int ray_open(struct net_device *dev)  	if (local->card_status == CARD_AWAITING_PARAM) {  		int i; -		DEBUG(1, "ray_open: doing init now !\n"); +		dev_dbg(&link->dev, "ray_open: doing init now !\n");  		/* Download startup parameters */  		if ((i = dl_startup_params(dev)) < 0) { @@ -1629,7 +1618,7 @@ static int ray_open(struct net_device *dev)  	else  		netif_start_queue(dev); -	DEBUG(2, "ray_open ending\n"); +	dev_dbg(&link->dev, "ray_open ending\n");  	return 0;  } /* end ray_open */ @@ -1640,7 +1629,7 @@ static int ray_dev_close(struct net_device *dev)  	struct pcmcia_device *link;  	link = local->finder; -	DEBUG(1, "ray_dev_close('%s')\n", dev->name); +	dev_dbg(&link->dev, "ray_dev_close('%s')\n", dev->name);  	link->open--;  	netif_stop_queue(dev); @@ -1656,7 +1645,7 @@ static int ray_dev_close(struct net_device *dev)  /*===========================================================================*/  static void ray_reset(struct net_device *dev)  { -	DEBUG(1, "ray_reset entered\n"); +	pr_debug("ray_reset entered\n");  	return;  } @@ -1669,17 +1658,17 @@ static int interrupt_ecf(ray_dev_t *local, int ccs)  	struct pcmcia_device *link = local->finder;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs interrupt_ecf - device not present\n"); +		dev_dbg(&link->dev, "ray_cs interrupt_ecf - device not present\n");  		return -1;  	} -	DEBUG(2, "interrupt_ecf(local=%p, ccs = 0x%x\n", local, ccs); +	dev_dbg(&link->dev, "interrupt_ecf(local=%p, ccs = 0x%x\n", local, ccs);  	while (i &&  	       (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) &  		ECF_INTR_SET))  		i--;  	if (i == 0) { -		DEBUG(2, "ray_cs interrupt_ecf card not ready for interrupt\n"); +		dev_dbg(&link->dev, "ray_cs interrupt_ecf card not ready for interrupt\n");  		return -1;  	}  	/* Fill the mailbox, then kick the card */ @@ -1698,12 +1687,12 @@ static int get_free_tx_ccs(ray_dev_t *local)  	struct pcmcia_device *link = local->finder;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs get_free_tx_ccs - device not present\n"); +		dev_dbg(&link->dev, "ray_cs get_free_tx_ccs - device not present\n");  		return ECARDGONE;  	}  	if (test_and_set_bit(0, &local->tx_ccs_lock)) { -		DEBUG(1, "ray_cs tx_ccs_lock busy\n"); +		dev_dbg(&link->dev, "ray_cs tx_ccs_lock busy\n");  		return ECCSBUSY;  	} @@ -1716,7 +1705,7 @@ static int get_free_tx_ccs(ray_dev_t *local)  		}  	}  	local->tx_ccs_lock = 0; -	DEBUG(2, "ray_cs ERROR no free tx CCS for raylink card\n"); +	dev_dbg(&link->dev, "ray_cs ERROR no free tx CCS for raylink card\n");  	return ECCSFULL;  } /* get_free_tx_ccs */ @@ -1730,11 +1719,11 @@ static int get_free_ccs(ray_dev_t *local)  	struct pcmcia_device *link = local->finder;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs get_free_ccs - device not present\n"); +		dev_dbg(&link->dev, "ray_cs get_free_ccs - device not present\n");  		return ECARDGONE;  	}  	if (test_and_set_bit(0, &local->ccs_lock)) { -		DEBUG(1, "ray_cs ccs_lock busy\n"); +		dev_dbg(&link->dev, "ray_cs ccs_lock busy\n");  		return ECCSBUSY;  	} @@ -1747,7 +1736,7 @@ static int get_free_ccs(ray_dev_t *local)  		}  	}  	local->ccs_lock = 0; -	DEBUG(1, "ray_cs ERROR no free CCS for raylink card\n"); +	dev_dbg(&link->dev, "ray_cs ERROR no free CCS for raylink card\n");  	return ECCSFULL;  } /* get_free_ccs */ @@ -1823,7 +1812,7 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)  	struct pcmcia_device *link = local->finder;  	struct status __iomem *p = local->sram + STATUS_BASE;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs net_device_stats - device not present\n"); +		dev_dbg(&link->dev, "ray_cs net_device_stats - device not present\n");  		return &local->stats;  	}  	if (readb(&p->mrx_overflow_for_host)) { @@ -1856,12 +1845,12 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value,  	struct ccs __iomem *pccs;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_update_parm - device not present\n"); +		dev_dbg(&link->dev, "ray_update_parm - device not present\n");  		return;  	}  	if ((ccsindex = get_free_ccs(local)) < 0) { -		DEBUG(0, "ray_update_parm - No free ccs\n"); +		dev_dbg(&link->dev, "ray_update_parm - No free ccs\n");  		return;  	}  	pccs = ccs_base(local) + ccsindex; @@ -1874,7 +1863,7 @@ static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value,  	}  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(0, "ray_cs associate failed - ECF not ready for intr\n"); +		dev_dbg(&link->dev, "ray_cs associate failed - ECF not ready for intr\n");  		writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);  	}  } @@ -1891,12 +1880,12 @@ static void ray_update_multi_list(struct net_device *dev, int all)  	void __iomem *p = local->sram + HOST_TO_ECF_BASE;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_update_multi_list - device not present\n"); +		dev_dbg(&link->dev, "ray_update_multi_list - device not present\n");  		return;  	} else -		DEBUG(2, "ray_update_multi_list(%p)\n", dev); +		dev_dbg(&link->dev, "ray_update_multi_list(%p)\n", dev);  	if ((ccsindex = get_free_ccs(local)) < 0) { -		DEBUG(1, "ray_update_multi - No free ccs\n"); +		dev_dbg(&link->dev, "ray_update_multi - No free ccs\n");  		return;  	}  	pccs = ccs_base(local) + ccsindex; @@ -1910,7 +1899,7 @@ static void ray_update_multi_list(struct net_device *dev, int all)  		for (dmip = &dev->mc_list; (dmi = *dmip) != NULL;  		     dmip = &dmi->next) {  			memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); -			DEBUG(1, +			dev_dbg(&link->dev,  			      "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",  			      dmi->dmi_addr[0], dmi->dmi_addr[1],  			      dmi->dmi_addr[2], dmi->dmi_addr[3], @@ -1921,12 +1910,12 @@ static void ray_update_multi_list(struct net_device *dev, int all)  		if (i > 256 / ADDRLEN)  			i = 256 / ADDRLEN;  		writeb((UCHAR) i, &pccs->var); -		DEBUG(1, "ray_cs update_multi %d addresses in list\n", i); +		dev_dbg(&link->dev, "ray_cs update_multi %d addresses in list\n", i);  		/* Interrupt the firmware to process the command */  		local->num_multi = i;  	}  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(1, +		dev_dbg(&link->dev,  		      "ray_cs update_multi failed - ECF not ready for intr\n");  		writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);  	} @@ -1938,11 +1927,11 @@ static void set_multicast_list(struct net_device *dev)  	ray_dev_t *local = netdev_priv(dev);  	UCHAR promisc; -	DEBUG(2, "ray_cs set_multicast_list(%p)\n", dev); +	pr_debug("ray_cs set_multicast_list(%p)\n", dev);  	if (dev->flags & IFF_PROMISC) {  		if (local->sparm.b5.a_promiscuous_mode == 0) { -			DEBUG(1, "ray_cs set_multicast_list promisc on\n"); +			pr_debug("ray_cs set_multicast_list promisc on\n");  			local->sparm.b5.a_promiscuous_mode = 1;  			promisc = 1;  			ray_update_parm(dev, OBJID_promiscuous_mode, @@ -1950,7 +1939,7 @@ static void set_multicast_list(struct net_device *dev)  		}  	} else {  		if (local->sparm.b5.a_promiscuous_mode == 1) { -			DEBUG(1, "ray_cs set_multicast_list promisc off\n"); +			pr_debug("ray_cs set_multicast_list promisc off\n");  			local->sparm.b5.a_promiscuous_mode = 0;  			promisc = 0;  			ray_update_parm(dev, OBJID_promiscuous_mode, @@ -1984,19 +1973,19 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  	if (dev == NULL)	/* Note that we want interrupts with dev->start == 0 */  		return IRQ_NONE; -	DEBUG(4, "ray_cs: interrupt for *dev=%p\n", dev); +	pr_debug("ray_cs: interrupt for *dev=%p\n", dev);  	local = netdev_priv(dev);  	link = (struct pcmcia_device *)local->finder;  	if (!pcmcia_dev_present(link)) { -		DEBUG(2, -		      "ray_cs interrupt from device not present or suspended.\n"); +		pr_debug( +			"ray_cs interrupt from device not present or suspended.\n");  		return IRQ_NONE;  	}  	rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index);  	if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { -		DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", rcsindex); +		dev_dbg(&link->dev, "ray_cs interrupt bad rcsindex = 0x%x\n", rcsindex);  		clear_interrupt(local);  		return IRQ_HANDLED;  	} @@ -2008,33 +1997,33 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  		case CCS_DOWNLOAD_STARTUP_PARAMS:	/* Happens in firmware someday */  			del_timer(&local->timer);  			if (status == CCS_COMMAND_COMPLETE) { -				DEBUG(1, +				dev_dbg(&link->dev,  				      "ray_cs interrupt download_startup_parameters OK\n");  			} else { -				DEBUG(1, +				dev_dbg(&link->dev,  				      "ray_cs interrupt download_startup_parameters fail\n");  			}  			break;  		case CCS_UPDATE_PARAMS: -			DEBUG(1, "ray_cs interrupt update params done\n"); +			dev_dbg(&link->dev, "ray_cs interrupt update params done\n");  			if (status != CCS_COMMAND_COMPLETE) {  				tmp =  				    readb(&pccs->var.update_param.  					  failure_cause); -				DEBUG(0, +				dev_dbg(&link->dev,  				      "ray_cs interrupt update params failed - reason %d\n",  				      tmp);  			}  			break;  		case CCS_REPORT_PARAMS: -			DEBUG(1, "ray_cs interrupt report params done\n"); +			dev_dbg(&link->dev, "ray_cs interrupt report params done\n");  			break;  		case CCS_UPDATE_MULTICAST_LIST:	/* Note that this CCS isn't returned */ -			DEBUG(1, +			dev_dbg(&link->dev,  			      "ray_cs interrupt CCS Update Multicast List done\n");  			break;  		case CCS_UPDATE_POWER_SAVINGS_MODE: -			DEBUG(1, +			dev_dbg(&link->dev,  			      "ray_cs interrupt update power save mode done\n");  			break;  		case CCS_START_NETWORK: @@ -2043,11 +2032,11 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  				if (readb  				    (&pccs->var.start_network.net_initiated) ==  				    1) { -					DEBUG(0, +					dev_dbg(&link->dev,  					      "ray_cs interrupt network \"%s\" started\n",  					      local->sparm.b4.a_current_ess_id);  				} else { -					DEBUG(0, +					dev_dbg(&link->dev,  					      "ray_cs interrupt network \"%s\" joined\n",  					      local->sparm.b4.a_current_ess_id);  				} @@ -2074,13 +2063,13 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  				del_timer(&local->timer);  				local->timer.expires = jiffies + HZ * 5;  				local->timer.data = (long)local; -				if (cmd == CCS_START_NETWORK) { -					DEBUG(0, +				if (status == CCS_START_NETWORK) { +					dev_dbg(&link->dev,  					      "ray_cs interrupt network \"%s\" start failed\n",  					      local->sparm.b4.a_current_ess_id);  					local->timer.function = &start_net;  				} else { -					DEBUG(0, +					dev_dbg(&link->dev,  					      "ray_cs interrupt network \"%s\" join failed\n",  					      local->sparm.b4.a_current_ess_id);  					local->timer.function = &join_net; @@ -2091,19 +2080,19 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  		case CCS_START_ASSOCIATION:  			if (status == CCS_COMMAND_COMPLETE) {  				local->card_status = CARD_ASSOC_COMPLETE; -				DEBUG(0, "ray_cs association successful\n"); +				dev_dbg(&link->dev, "ray_cs association successful\n");  			} else { -				DEBUG(0, "ray_cs association failed,\n"); +				dev_dbg(&link->dev, "ray_cs association failed,\n");  				local->card_status = CARD_ASSOC_FAILED;  				join_net((u_long) local);  			}  			break;  		case CCS_TX_REQUEST:  			if (status == CCS_COMMAND_COMPLETE) { -				DEBUG(3, +				dev_dbg(&link->dev,  				      "ray_cs interrupt tx request complete\n");  			} else { -				DEBUG(1, +				dev_dbg(&link->dev,  				      "ray_cs interrupt tx request failed\n");  			}  			if (!sniffer) @@ -2111,21 +2100,21 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  			netif_wake_queue(dev);  			break;  		case CCS_TEST_MEMORY: -			DEBUG(1, "ray_cs interrupt mem test done\n"); +			dev_dbg(&link->dev, "ray_cs interrupt mem test done\n");  			break;  		case CCS_SHUTDOWN: -			DEBUG(1, +			dev_dbg(&link->dev,  			      "ray_cs interrupt Unexpected CCS returned - Shutdown\n");  			break;  		case CCS_DUMP_MEMORY: -			DEBUG(1, "ray_cs interrupt dump memory done\n"); +			dev_dbg(&link->dev, "ray_cs interrupt dump memory done\n");  			break;  		case CCS_START_TIMER: -			DEBUG(2, +			dev_dbg(&link->dev,  			      "ray_cs interrupt DING - raylink timer expired\n");  			break;  		default: -			DEBUG(1, +			dev_dbg(&link->dev,  			      "ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n",  			      rcsindex, cmd);  		} @@ -2139,7 +2128,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  			ray_rx(dev, local, prcs);  			break;  		case REJOIN_NET_COMPLETE: -			DEBUG(1, "ray_cs interrupt rejoin net complete\n"); +			dev_dbg(&link->dev, "ray_cs interrupt rejoin net complete\n");  			local->card_status = CARD_ACQ_COMPLETE;  			/* do we need to clear tx buffers CCS's? */  			if (local->sparm.b4.a_network_type == ADHOC) { @@ -2149,7 +2138,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  				memcpy_fromio(&local->bss_id,  					      prcs->var.rejoin_net_complete.  					      bssid, ADDRLEN); -				DEBUG(1, +				dev_dbg(&link->dev,  				      "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n",  				      local->bss_id[0], local->bss_id[1],  				      local->bss_id[2], local->bss_id[3], @@ -2159,15 +2148,15 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)  			}  			break;  		case ROAMING_INITIATED: -			DEBUG(1, "ray_cs interrupt roaming initiated\n"); +			dev_dbg(&link->dev, "ray_cs interrupt roaming initiated\n");  			netif_stop_queue(dev);  			local->card_status = CARD_DOING_ACQ;  			break;  		case JAPAN_CALL_SIGN_RXD: -			DEBUG(1, "ray_cs interrupt japan call sign rx\n"); +			dev_dbg(&link->dev, "ray_cs interrupt japan call sign rx\n");  			break;  		default: -			DEBUG(1, +			dev_dbg(&link->dev,  			      "ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",  			      rcsindex,  			      (unsigned int)readb(&prcs->interrupt_id)); @@ -2186,7 +2175,7 @@ static void ray_rx(struct net_device *dev, ray_dev_t *local,  	int rx_len;  	unsigned int pkt_addr;  	void __iomem *pmsg; -	DEBUG(4, "ray_rx process rx packet\n"); +	pr_debug("ray_rx process rx packet\n");  	/* Calculate address of packet within Rx buffer */  	pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8) @@ -2199,28 +2188,28 @@ static void ray_rx(struct net_device *dev, ray_dev_t *local,  	pmsg = local->rmem + pkt_addr;  	switch (readb(pmsg)) {  	case DATA_TYPE: -		DEBUG(4, "ray_rx data type\n"); +		pr_debug("ray_rx data type\n");  		rx_data(dev, prcs, pkt_addr, rx_len);  		break;  	case AUTHENTIC_TYPE: -		DEBUG(4, "ray_rx authentic type\n"); +		pr_debug("ray_rx authentic type\n");  		if (sniffer)  			rx_data(dev, prcs, pkt_addr, rx_len);  		else  			rx_authenticate(local, prcs, pkt_addr, rx_len);  		break;  	case DEAUTHENTIC_TYPE: -		DEBUG(4, "ray_rx deauth type\n"); +		pr_debug("ray_rx deauth type\n");  		if (sniffer)  			rx_data(dev, prcs, pkt_addr, rx_len);  		else  			rx_deauthenticate(local, prcs, pkt_addr, rx_len);  		break;  	case NULL_MSG_TYPE: -		DEBUG(3, "ray_cs rx NULL msg\n"); +		pr_debug("ray_cs rx NULL msg\n");  		break;  	case BEACON_TYPE: -		DEBUG(4, "ray_rx beacon type\n"); +		pr_debug("ray_rx beacon type\n");  		if (sniffer)  			rx_data(dev, prcs, pkt_addr, rx_len); @@ -2233,7 +2222,7 @@ static void ray_rx(struct net_device *dev, ray_dev_t *local,  		ray_get_stats(dev);  		break;  	default: -		DEBUG(0, "ray_cs unknown pkt type %2x\n", +		pr_debug("ray_cs unknown pkt type %2x\n",  		      (unsigned int)readb(pmsg));  		break;  	} @@ -2262,7 +2251,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,  			    rx_len >  			    (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN +  			     FCS_LEN)) { -				DEBUG(0, +				pr_debug(  				      "ray_cs invalid packet length %d received \n",  				      rx_len);  				return; @@ -2273,17 +2262,17 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,  			    rx_len >  			    (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN +  			     FCS_LEN)) { -				DEBUG(0, +				pr_debug(  				      "ray_cs invalid packet length %d received \n",  				      rx_len);  				return;  			}  		}  	} -	DEBUG(4, "ray_cs rx_data packet\n"); +	pr_debug("ray_cs rx_data packet\n");  	/* If fragmented packet, verify sizes of fragments add up */  	if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { -		DEBUG(1, "ray_cs rx'ed fragment\n"); +		pr_debug("ray_cs rx'ed fragment\n");  		tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8)  		    + readb(&prcs->var.rx_packet.totalpacketlength[1]);  		total_len = tmp; @@ -2301,7 +2290,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,  		} while (1);  		if (tmp < 0) { -			DEBUG(0, +			pr_debug(  			      "ray_cs rx_data fragment lengths don't add up\n");  			local->stats.rx_dropped++;  			release_frag_chain(local, prcs); @@ -2313,7 +2302,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,  	skb = dev_alloc_skb(total_len + 5);  	if (skb == NULL) { -		DEBUG(0, "ray_cs rx_data could not allocate skb\n"); +		pr_debug("ray_cs rx_data could not allocate skb\n");  		local->stats.rx_dropped++;  		if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF)  			release_frag_chain(local, prcs); @@ -2321,7 +2310,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,  	}  	skb_reserve(skb, 2);	/* Align IP on 16 byte (TBD check this) */ -	DEBUG(4, "ray_cs rx_data total_len = %x, rx_len = %x\n", total_len, +	pr_debug("ray_cs rx_data total_len = %x, rx_len = %x\n", total_len,  	      rx_len);  /************************/ @@ -2354,7 +2343,7 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs,  	tmp = 17;  	if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) {  		prcslink = prcs; -		DEBUG(1, "ray_cs rx_data in fragment loop\n"); +		pr_debug("ray_cs rx_data in fragment loop\n");  		do {  			prcslink = rcs_base(local)  			    + @@ -2426,8 +2415,8 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)  	memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN);  	memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); -#ifdef PCMCIA_DEBUG -	if (pc_debug > 3) { +#if 0 +	if {  		print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ",  			       DUMP_PREFIX_NONE, 16, 1,  			       skb->data, 64, true); @@ -2441,7 +2430,7 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)  	if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) {  		/* not a snap type so leave it alone */ -		DEBUG(3, "ray_cs untranslate NOT SNAP %02x %02x %02x\n", +		pr_debug("ray_cs untranslate NOT SNAP %02x %02x %02x\n",  		      psnap->dsap, psnap->ssap, psnap->ctrl);  		delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; @@ -2450,7 +2439,7 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)  	} else { /* Its a SNAP */  		if (memcmp(psnap->org, org_bridge, 3) == 0) {  		/* EtherII and nuke the LLC */ -			DEBUG(3, "ray_cs untranslate Bridge encap\n"); +			pr_debug("ray_cs untranslate Bridge encap\n");  			delta = RX_MAC_HEADER_LENGTH  			    + sizeof(struct snaphdr_t) - ETH_HLEN;  			peth = (struct ethhdr *)(skb->data + delta); @@ -2459,14 +2448,14 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)  			switch (ntohs(type)) {  			case ETH_P_IPX:  			case ETH_P_AARP: -				DEBUG(3, "ray_cs untranslate RFC IPX/AARP\n"); +				pr_debug("ray_cs untranslate RFC IPX/AARP\n");  				delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;  				peth = (struct ethhdr *)(skb->data + delta);  				peth->h_proto =  				    htons(len - RX_MAC_HEADER_LENGTH);  				break;  			default: -				DEBUG(3, "ray_cs untranslate RFC default\n"); +				pr_debug("ray_cs untranslate RFC default\n");  				delta = RX_MAC_HEADER_LENGTH +  				    sizeof(struct snaphdr_t) - ETH_HLEN;  				peth = (struct ethhdr *)(skb->data + delta); @@ -2482,12 +2471,12 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)  	}  /* TBD reserve  skb_reserve(skb, delta); */  	skb_pull(skb, delta); -	DEBUG(3, "untranslate after skb_pull(%d), skb->data = %p\n", delta, +	pr_debug("untranslate after skb_pull(%d), skb->data = %p\n", delta,  	      skb->data);  	memcpy(peth->h_dest, destaddr, ADDRLEN);  	memcpy(peth->h_source, srcaddr, ADDRLEN); -#ifdef PCMCIA_DEBUG -	if (pc_debug > 3) { +#if 0 +	{  		int i;  		printk(KERN_DEBUG "skb->data after untranslate:");  		for (i = 0; i < 64; i++) @@ -2529,7 +2518,7 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs)  	while (tmp--) {  		writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);  		if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { -			DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", +			pr_debug("ray_cs interrupt bad rcsindex = 0x%x\n",  			      rcsindex);  			break;  		} @@ -2543,9 +2532,9 @@ static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs)  static void authenticate(ray_dev_t *local)  {  	struct pcmcia_device *link = local->finder; -	DEBUG(0, "ray_cs Starting authentication.\n"); +	dev_dbg(&link->dev, "ray_cs Starting authentication.\n");  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs authenticate - device not present\n"); +		dev_dbg(&link->dev, "ray_cs authenticate - device not present\n");  		return;  	} @@ -2573,11 +2562,11 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,  	copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff);  	/* if we are trying to get authenticated */  	if (local->sparm.b4.a_network_type == ADHOC) { -		DEBUG(1, "ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", +		pr_debug("ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n",  		      msg->var[0], msg->var[1], msg->var[2], msg->var[3],  		      msg->var[4], msg->var[5]);  		if (msg->var[2] == 1) { -			DEBUG(0, "ray_cs Sending authentication response.\n"); +			pr_debug("ray_cs Sending authentication response.\n");  			if (!build_auth_frame  			    (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) {  				local->authentication_state = NEED_TO_AUTH; @@ -2591,13 +2580,13 @@ static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,  			/* Verify authentication sequence #2 and success */  			if (msg->var[2] == 2) {  				if ((msg->var[3] | msg->var[4]) == 0) { -					DEBUG(1, "Authentication successful\n"); +					pr_debug("Authentication successful\n");  					local->card_status = CARD_AUTH_COMPLETE;  					associate(local);  					local->authentication_state =  					    AUTHENTICATED;  				} else { -					DEBUG(0, "Authentication refused\n"); +					pr_debug("Authentication refused\n");  					local->card_status = CARD_AUTH_REFUSED;  					join_net((u_long) local);  					local->authentication_state = @@ -2617,22 +2606,22 @@ static void associate(ray_dev_t *local)  	struct net_device *dev = link->priv;  	int ccsindex;  	if (!(pcmcia_dev_present(link))) { -		DEBUG(2, "ray_cs associate - device not present\n"); +		dev_dbg(&link->dev, "ray_cs associate - device not present\n");  		return;  	}  	/* If no tx buffers available, return */  	if ((ccsindex = get_free_ccs(local)) < 0) {  /* TBD should never be here but... what if we are? */ -		DEBUG(1, "ray_cs associate - No free ccs\n"); +		dev_dbg(&link->dev, "ray_cs associate - No free ccs\n");  		return;  	} -	DEBUG(1, "ray_cs Starting association with access point\n"); +	dev_dbg(&link->dev, "ray_cs Starting association with access point\n");  	pccs = ccs_base(local) + ccsindex;  	/* fill in the CCS */  	writeb(CCS_START_ASSOCIATION, &pccs->cmd);  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(1, "ray_cs associate failed - ECF not ready for intr\n"); +		dev_dbg(&link->dev, "ray_cs associate failed - ECF not ready for intr\n");  		writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);  		del_timer(&local->timer); @@ -2655,7 +2644,7 @@ static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs,  /*  UCHAR buff[256];      struct rx_msg *msg = (struct rx_msg *)buff;  */ -	DEBUG(0, "Deauthentication frame received\n"); +	pr_debug("Deauthentication frame received\n");  	local->authentication_state = UNAUTHENTICATED;  	/* Need to reauthenticate or rejoin depending on reason code */  /*  copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); @@ -2823,7 +2812,7 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)  	/* If no tx buffers available, return */  	if ((ccsindex = get_free_tx_ccs(local)) < 0) { -		DEBUG(1, "ray_cs send authenticate - No free tx ccs\n"); +		pr_debug("ray_cs send authenticate - No free tx ccs\n");  		return -1;  	} @@ -2855,7 +2844,7 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)  	/* Interrupt the firmware to process the command */  	if (interrupt_ecf(local, ccsindex)) { -		DEBUG(1, +		pr_debug(  		      "ray_cs send authentication request failed - ECF not ready for intr\n");  		writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);  		return -1; @@ -2942,9 +2931,9 @@ static int __init init_ray_cs(void)  {  	int rc; -	DEBUG(1, "%s\n", rcsid); +	pr_debug("%s\n", rcsid);  	rc = pcmcia_register_driver(&ray_driver); -	DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n", +	pr_debug("raylink init_module register_pcmcia_driver returns 0x%x\n",  	      rc);  #ifdef CONFIG_PROC_FS @@ -2964,7 +2953,7 @@ static int __init init_ray_cs(void)  static void __exit exit_ray_cs(void)  { -	DEBUG(0, "ray_cs: cleanup_module\n"); +	pr_debug("ray_cs: cleanup_module\n");  #ifdef CONFIG_PROC_FS  	remove_proc_entry("driver/ray_cs/ray_cs", NULL); diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 891bdab4988..7b9621de239 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c @@ -67,23 +67,7 @@  /* For rough constant delay */  #define WL3501_NOPLOOP(n) { int x = 0; while (x++ < n) slow_down_io(); } -/* - * All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If you do not - * define PCMCIA_DEBUG at all, all the debug code will be left out.  If you - * compile with PCMCIA_DEBUG=0, the debug code will be present but disabled -- - * but it can then be enabled for specific modules at load time with a - * 'pc_debug=#' option to insmod. - */ -#define PCMCIA_DEBUG 0 -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define dprintk(n, format, args...) \ -	{ if (pc_debug > (n)) \ -		printk(KERN_INFO "%s: " format "\n", __func__ , ##args); } -#else -#define dprintk(n, format, args...) -#endif +  #define wl3501_outb(a, b) { outb(a, b); slow_down_io(); }  #define wl3501_outb_p(a, b) { outb_p(a, b); slow_down_io(); } @@ -684,10 +668,10 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)  	int matchflag = 0;  	struct wl3501_scan_confirm sig; -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));  	if (sig.status == WL3501_STATUS_SUCCESS) { -		dprintk(3, "success"); +		pr_debug("success");  		if ((this->net_type == IW_MODE_INFRA &&  		     (sig.cap_info & WL3501_MGMT_CAPABILITY_ESS)) ||  		    (this->net_type == IW_MODE_ADHOC && @@ -722,7 +706,7 @@ static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr)  			}  		}  	} else if (sig.status == WL3501_STATUS_TIMEOUT) { -		dprintk(3, "timeout"); +		pr_debug("timeout");  		this->join_sta_bss = 0;  		for (i = this->join_sta_bss; i < this->bss_cnt; i++)  			if (!wl3501_mgmt_join(this, i)) @@ -879,7 +863,7 @@ static int wl3501_mgmt_auth(struct wl3501_card *this)  		.timeout = 1000,  	}; -	dprintk(3, "entry"); +	pr_debug("entry");  	memcpy(sig.mac_addr, this->bssid, ETH_ALEN);  	return wl3501_esbq_exec(this, &sig, sizeof(sig));  } @@ -893,7 +877,7 @@ static int wl3501_mgmt_association(struct wl3501_card *this)  		.cap_info	 = this->cap_info,  	}; -	dprintk(3, "entry"); +	pr_debug("entry");  	memcpy(sig.mac_addr, this->bssid, ETH_ALEN);  	return wl3501_esbq_exec(this, &sig, sizeof(sig));  } @@ -903,7 +887,7 @@ static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr)  	struct wl3501_card *this = netdev_priv(dev);  	struct wl3501_join_confirm sig; -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));  	if (sig.status == WL3501_STATUS_SUCCESS) {  		if (this->net_type == IW_MODE_INFRA) { @@ -962,7 +946,7 @@ static inline void wl3501_md_confirm_interrupt(struct net_device *dev,  {  	struct wl3501_md_confirm sig; -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));  	wl3501_free_tx_buffer(this, sig.data);  	if (netif_queue_stopped(dev)) @@ -1017,7 +1001,7 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,  static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this,  						u16 addr, void *sig, int size)  { -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &this->sig_get_confirm,  			    sizeof(this->sig_get_confirm));  	wake_up(&this->wait); @@ -1029,7 +1013,7 @@ static inline void wl3501_start_confirm_interrupt(struct net_device *dev,  {  	struct wl3501_start_confirm sig; -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));  	if (sig.status == WL3501_STATUS_SUCCESS)  		netif_wake_queue(dev); @@ -1041,7 +1025,7 @@ static inline void wl3501_assoc_confirm_interrupt(struct net_device *dev,  	struct wl3501_card *this = netdev_priv(dev);  	struct wl3501_assoc_confirm sig; -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));  	if (sig.status == WL3501_STATUS_SUCCESS) @@ -1053,7 +1037,7 @@ static inline void wl3501_auth_confirm_interrupt(struct wl3501_card *this,  {  	struct wl3501_auth_confirm sig; -	dprintk(3, "entry"); +	pr_debug("entry");  	wl3501_get_from_wla(this, addr, &sig, sizeof(sig));  	if (sig.status == WL3501_STATUS_SUCCESS) @@ -1069,7 +1053,7 @@ static inline void wl3501_rx_interrupt(struct net_device *dev)  	u8 sig_id;  	struct wl3501_card *this = netdev_priv(dev); -	dprintk(3, "entry"); +	pr_debug("entry");  loop:  	morepkts = 0;  	if (!wl3501_esbq_confirm(this)) @@ -1302,7 +1286,7 @@ static int wl3501_reset(struct net_device *dev)  	wl3501_ack_interrupt(this);  	wl3501_unblock_interrupt(this);  	wl3501_mgmt_scan(this, 100); -	dprintk(1, "%s: device reset", dev->name); +	pr_debug("%s: device reset", dev->name);  	rc = 0;  out:  	return rc; @@ -1376,7 +1360,7 @@ static int wl3501_open(struct net_device *dev)  	link->open++;  	/* Initial WL3501 firmware */ -	dprintk(1, "%s: Initialize WL3501 firmware...", dev->name); +	pr_debug("%s: Initialize WL3501 firmware...", dev->name);  	if (wl3501_init_firmware(this))  		goto fail;  	/* Initial device variables */ @@ -1388,7 +1372,7 @@ static int wl3501_open(struct net_device *dev)  	wl3501_unblock_interrupt(this);  	wl3501_mgmt_scan(this, 100);  	rc = 0; -	dprintk(1, "%s: WL3501 opened", dev->name); +	pr_debug("%s: WL3501 opened", dev->name);  	printk(KERN_INFO "%s: Card Name: %s\n"  			 "%s: Firmware Date: %s\n",  			 dev->name, this->card_name, @@ -1914,8 +1898,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev)  	p_dev->io.IOAddrLines	= 5;  	/* Interrupt setup */ -	p_dev->irq.Attributes	= IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	p_dev->irq.IRQInfo1	= IRQ_LEVEL_ID; +	p_dev->irq.Attributes	= IRQ_TYPE_DYNAMIC_SHARING;  	p_dev->irq.Handler = wl3501_interrupt;  	/* General socket configuration */ @@ -1938,16 +1921,13 @@ static int wl3501_probe(struct pcmcia_device *p_dev)  	dev->wireless_handlers	= &wl3501_handler_def;  	SET_ETHTOOL_OPS(dev, &ops);  	netif_stop_queue(dev); -	p_dev->priv = p_dev->irq.Instance = dev; +	p_dev->priv = dev;  	return wl3501_config(p_dev);  out_link:  	return -ENOMEM;  } -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  /**   * wl3501_config - configure the PCMCIA socket and make eth device available   * @link - FILL_IN @@ -1959,7 +1939,7 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)  static int wl3501_config(struct pcmcia_device *link)  {  	struct net_device *dev = link->priv; -	int i = 0, j, last_fn, last_ret; +	int i = 0, j, ret;  	struct wl3501_card *this;  	/* Try allocating IO ports.  This tries a few fixed addresses.  If you @@ -1975,24 +1955,26 @@ static int wl3501_config(struct pcmcia_device *link)  		if (i == 0)  			break;  	} -	if (i != 0) { -		cs_error(link, RequestIO, i); +	if (i != 0)  		goto failed; -	}  	/* Now allocate an interrupt line. Note that this does not actually  	 * assign a handler to the interrupt. */ -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret) +		goto failed;  	/* This actually configures the PCMCIA socket -- setting up the I/O  	 * windows and the interrupt mapping.  */ -	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	dev->irq = link->irq.AssignedIRQ;  	dev->base_addr = link->io.BasePort1; -	SET_NETDEV_DEV(dev, &handle_to_dev(link)); +	SET_NETDEV_DEV(dev, &link->dev);  	if (register_netdev(dev)) {  		printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n");  		goto failed; @@ -2041,8 +2023,6 @@ static int wl3501_config(struct pcmcia_device *link)  	netif_start_queue(dev);  	return 0; -cs_failed: -	cs_error(link, last_fn, last_ret);  failed:  	wl3501_release(link);  	return -ENODEV; diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 8fdfa4f537a..7dd370fa343 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -67,14 +67,6 @@ MODULE_LICENSE("Dual MPL/GPL");  INT_MODULE_PARM(epp_mode, 1); -#ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"parport_cs.c 1.29 2002/10/11 06:57:41 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -103,7 +95,7 @@ static int parport_probe(struct pcmcia_device *link)  {      parport_info_t *info; -    DEBUG(0, "parport_attach()\n"); +    dev_dbg(&link->dev, "parport_attach()\n");      /* Create new parport device */      info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -114,7 +106,6 @@ static int parport_probe(struct pcmcia_device *link)      link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;      link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO; @@ -132,7 +123,7 @@ static int parport_probe(struct pcmcia_device *link)  static void parport_detach(struct pcmcia_device *link)  { -    DEBUG(0, "parport_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "parport_detach\n");      parport_cs_release(link); @@ -147,9 +138,6 @@ static void parport_detach(struct pcmcia_device *link)  ======================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int parport_config_check(struct pcmcia_device *p_dev,  				cistpl_cftable_entry_t *cfg,  				cistpl_cftable_entry_t *dflt, @@ -178,18 +166,20 @@ static int parport_config(struct pcmcia_device *link)  {      parport_info_t *info = link->priv;      struct parport *p; -    int last_ret, last_fn; +    int ret; -    DEBUG(0, "parport_config(0x%p)\n", link); +    dev_dbg(&link->dev, "parport_config\n"); -    last_ret = pcmcia_loop_config(link, parport_config_check, NULL); -    if (last_ret) { -	    cs_error(link, RequestIO, last_ret); +    ret = pcmcia_loop_config(link, parport_config_check, NULL); +    if (ret)  	    goto failed; -    } -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      p = parport_pc_probe_port(link->io.BasePort1, link->io.BasePort2,  			      link->irq.AssignedIRQ, PARPORT_DMA_NONE, @@ -213,8 +203,6 @@ static int parport_config(struct pcmcia_device *link)      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      parport_cs_release(link);      return -ENODEV; @@ -232,7 +220,7 @@ static void parport_cs_release(struct pcmcia_device *link)  {  	parport_info_t *info = link->priv; -	DEBUG(0, "parport_release(0x%p)\n", link); +	dev_dbg(&link->dev, "parport_release\n");  	if (info->ndev) {  		struct parport *p = info->port; diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index b952ebc7a78..416f6ac65b7 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c @@ -645,10 +645,13 @@ void __init detect_intel_iommu(void)  			       "x2apic and Intr-remapping.\n");  #endif  #ifdef CONFIG_DMAR -		if (ret && !no_iommu && !iommu_detected && !swiotlb && -		    !dmar_disabled) +		if (ret && !no_iommu && !iommu_detected && !dmar_disabled)  			iommu_detected = 1;  #endif +#ifdef CONFIG_X86 +		if (ret) +			x86_init.iommu.iommu_init = intel_iommu_init; +#endif  	}  	early_acpi_os_unmap_memory(dmar_tbl, dmar_tbl_size);  	dmar_tbl = NULL; diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1840a0578a4..9261327b49f 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3266,7 +3266,7 @@ int __init intel_iommu_init(void)  	 * Check the need for DMA-remapping initialization now.  	 * Above initialization will also be used by Interrupt-remapping.  	 */ -	if (no_iommu || swiotlb || dmar_disabled) +	if (no_iommu || dmar_disabled)  		return -ENODEV;  	iommu_init_mempool(); @@ -3287,7 +3287,9 @@ int __init intel_iommu_init(void)  	"PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");  	init_timer(&unmap_timer); -	force_iommu = 1; +#ifdef CONFIG_SWIOTLB +	swiotlb = 0; +#endif  	dma_ops = &intel_dma_ops;  	init_iommu_sysfs(); diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index 17f38a781d4..f3ccbccf5f2 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -17,24 +17,6 @@ menuconfig PCCARD  if PCCARD -config PCMCIA_DEBUG -	bool "Enable PCCARD debugging" -	help -	  Say Y here to enable PCMCIA subsystem debugging.  You -	  will need to choose the debugging level either via the -	  kernel command line, or module options depending whether -	  you build the PCMCIA as modules. - -	  The kernel command line options are: -	    pcmcia_core.pc_debug=N -	    pcmcia.pc_debug=N -	    sa11xx_core.pc_debug=N - -	  The module option is called pc_debug=N - -	  In all the above examples, N is the debugging verbosity -	  level. -  config PCMCIA  	tristate "16-bit PCMCIA support"  	select CRC32 @@ -196,9 +178,13 @@ config PCMCIA_BCM63XX  	tristate "bcm63xx pcmcia support"  	depends on BCM63XX && PCMCIA +config PCMCIA_SOC_COMMON +	bool +  config PCMCIA_SA1100  	tristate "SA1100 support"  	depends on ARM && ARCH_SA1100 && PCMCIA +	select PCMCIA_SOC_COMMON  	help  	  Say Y here to include support for SA11x0-based PCMCIA or CF  	  sockets, found on HP iPAQs, Yopy, and other StrongARM(R)/ @@ -209,6 +195,7 @@ config PCMCIA_SA1100  config PCMCIA_SA1111  	tristate "SA1111 support"  	depends on ARM && ARCH_SA1100 && SA1111 && PCMCIA +	select PCMCIA_SOC_COMMON  	help  	  Say Y  here to include support for SA1111-based PCMCIA or CF  	  sockets, found on the Jornada 720, Graphicsmaster and other @@ -222,9 +209,28 @@ config PCMCIA_PXA2XX  	depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \  		    || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \  		    || ARCH_VIPER || ARCH_PXA_ESERIES || MACH_STARGATE2) +	select PCMCIA_SOC_COMMON  	help  	  Say Y here to include support for the PXA2xx PCMCIA controller +config PCMCIA_DEBUG +	bool "Enable debugging" +	depends on (PCMCIA_SA1111 || PCMCIA_SA1100 || PCMCIA_PXA2XX) +	help +	  Say Y here to enable debugging for the SoC PCMCIA layer. +	  You will need to choose the debugging level either via the +	  kernel command line, or module options depending whether +	  you build the drivers as modules. + +	  The kernel command line options are: +	    sa11xx_core.pc_debug=N +	    pxa2xx_core.pc_debug=N + +	  The module option is called pc_debug=N + +	  In all the above examples, N is the debugging verbosity +	  level. +  config PCMCIA_PROBE  	bool  	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index a03a38acd77..38293831399 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile @@ -22,8 +22,9 @@ obj-$(CONFIG_I82365)				+= i82365.o  obj-$(CONFIG_I82092)				+= i82092.o  obj-$(CONFIG_TCIC)				+= tcic.o  obj-$(CONFIG_PCMCIA_M8XX)			+= m8xx_pcmcia.o -obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_core.o sa1100_cs.o -obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_core.o sa1111_cs.o +obj-$(CONFIG_PCMCIA_SOC_COMMON)			+= soc_common.o +obj-$(CONFIG_PCMCIA_SA1100)			+= sa11xx_base.o sa1100_cs.o +obj-$(CONFIG_PCMCIA_SA1111)			+= sa11xx_base.o sa1111_cs.o  obj-$(CONFIG_M32R_PCC)				+= m32r_pcc.o  obj-$(CONFIG_M32R_CFC)				+= m32r_cfc.o  obj-$(CONFIG_PCMCIA_AU1X00)			+= au1x00_ss.o @@ -35,9 +36,6 @@ obj-$(CONFIG_BFIN_CFPCMCIA)			+= bfin_cf_pcmcia.o  obj-$(CONFIG_AT91_CF)				+= at91_cf.o  obj-$(CONFIG_ELECTRA_CF)			+= electra_cf.o -sa11xx_core-y					+= soc_common.o sa11xx_base.o -pxa2xx_core-y					+= soc_common.o pxa2xx_base.o -  au1x00_ss-y					+= au1000_generic.o  au1x00_ss-$(CONFIG_MIPS_PB1000)			+= au1000_pb1x00.o  au1x00_ss-$(CONFIG_MIPS_PB1100)			+= au1000_pb1x00.o @@ -77,4 +75,4 @@ pxa2xx-obj-$(CONFIG_MACH_PALMLD)		+= pxa2xx_palmld.o  pxa2xx-obj-$(CONFIG_MACH_E740)			+= pxa2xx_e740.o  pxa2xx-obj-$(CONFIG_MACH_STARGATE2)		+= pxa2xx_stargate2.o -obj-$(CONFIG_PCMCIA_PXA2XX)			+= pxa2xx_core.o $(pxa2xx-obj-y) +obj-$(CONFIG_PCMCIA_PXA2XX)			+= pxa2xx_base.o $(pxa2xx-obj-y) diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index db77e1f3309..4cd70d05681 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -91,7 +91,7 @@ static u_int xlate_rom_addr(void __iomem *b, u_int addr)  static void cb_release_cis_mem(struct pcmcia_socket * s)  {  	if (s->cb_cis_virt) { -		cs_dbg(s, 1, "cb_release_cis_mem()\n"); +		dev_dbg(&s->dev, "cb_release_cis_mem()\n");  		iounmap(s->cb_cis_virt);  		s->cb_cis_virt = NULL;  		s->cb_cis_res = NULL; @@ -132,7 +132,7 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void  	struct pci_dev *dev;  	struct resource *res; -	cs_dbg(s, 3, "read_cb_mem(%d, %#x, %u)\n", space, addr, len); +	dev_dbg(&s->dev, "read_cb_mem(%d, %#x, %u)\n", space, addr, len);  	dev = pci_get_slot(s->cb_dev->subordinate, 0);  	if (!dev) diff --git a/drivers/pcmcia/cirrus.h b/drivers/pcmcia/cirrus.h index ecd4fc7f666..446a4576e73 100644 --- a/drivers/pcmcia/cirrus.h +++ b/drivers/pcmcia/cirrus.h @@ -30,16 +30,6 @@  #ifndef _LINUX_CIRRUS_H  #define _LINUX_CIRRUS_H -#ifndef PCI_VENDOR_ID_CIRRUS -#define PCI_VENDOR_ID_CIRRUS		0x1013 -#endif -#ifndef PCI_DEVICE_ID_CIRRUS_6729 -#define PCI_DEVICE_ID_CIRRUS_6729	0x1100 -#endif -#ifndef PCI_DEVICE_ID_CIRRUS_6832 -#define PCI_DEVICE_ID_CIRRUS_6832	0x1110 -#endif -  #define PD67_MISC_CTL_1		0x16	/* Misc control 1 */  #define PD67_FIFO_CTL		0x17	/* FIFO control */  #define PD67_MISC_CTL_2		0x1E	/* Misc control 2 */ diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c index 6c4a4fc8363..8c1b73cf021 100644 --- a/drivers/pcmcia/cistpl.c +++ b/drivers/pcmcia/cistpl.c @@ -138,7 +138,7 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,      void __iomem *sys, *end;      unsigned char *buf = ptr; -    cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len); +    dev_dbg(&s->dev, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);      if (attr & IS_INDIRECT) {  	/* Indirect accesses use a bunch of special registers at fixed @@ -190,7 +190,7 @@ int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,  	    addr = 0;  	}      } -    cs_dbg(s, 3, "  %#2.2x %#2.2x %#2.2x %#2.2x ...\n", +    dev_dbg(&s->dev, "  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",  	  *(u_char *)(ptr+0), *(u_char *)(ptr+1),  	  *(u_char *)(ptr+2), *(u_char *)(ptr+3));      return 0; @@ -204,7 +204,7 @@ void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,      void __iomem *sys, *end;      unsigned char *buf = ptr; -    cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len); +    dev_dbg(&s->dev, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);      if (attr & IS_INDIRECT) {  	/* Indirect accesses use a bunch of special registers at fixed @@ -584,7 +584,7 @@ int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_  	ofs += link[1] + 2;      }      if (i == MAX_TUPLES) { -	cs_dbg(s, 1, "cs: overrun in pcmcia_get_next_tuple\n"); +	dev_dbg(&s->dev, "cs: overrun in pcmcia_get_next_tuple\n");  	return -ENOSPC;      } @@ -1440,7 +1440,7 @@ int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)  	break;      }      if (ret) -	    __cs_dbg(0, "parse_tuple failed %d\n", ret); +	    pr_debug("parse_tuple failed %d\n", ret);      return ret;  }  EXPORT_SYMBOL(pcmcia_parse_tuple); @@ -1482,6 +1482,67 @@ done:  }  EXPORT_SYMBOL(pccard_read_tuple); + +/** + * pccard_loop_tuple() - loop over tuples in the CIS + * @s:		the struct pcmcia_socket where the card is inserted + * @function:	the device function we loop for + * @code:	which CIS code shall we look for? + * @parse:	buffer where the tuple shall be parsed (or NULL, if no parse) + * @priv_data:	private data to be passed to the loop_tuple function. + * @loop_tuple:	function to call for each CIS entry of type @function. IT + *		gets passed the raw tuple, the paresed tuple (if @parse is + *		set) and @priv_data. + * + * pccard_loop_tuple() loops over all CIS entries of type @function, and + * calls the @loop_tuple function for each entry. If the call to @loop_tuple + * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. + */ +int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, +		      cisdata_t code, cisparse_t *parse, void *priv_data, +		      int (*loop_tuple) (tuple_t *tuple, +					 cisparse_t *parse, +					 void *priv_data)) +{ +	tuple_t tuple; +	cisdata_t *buf; +	int ret; + +	buf = kzalloc(256, GFP_KERNEL); +	if (buf == NULL) { +		dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n"); +		return -ENOMEM; +	} + +	tuple.TupleData = buf; +	tuple.TupleDataMax = 255; +	tuple.TupleOffset = 0; +	tuple.DesiredTuple = code; +	tuple.Attributes = 0; + +	ret = pccard_get_first_tuple(s, function, &tuple); +	while (!ret) { +		if (pccard_get_tuple_data(s, &tuple)) +			goto next_entry; + +		if (parse) +			if (pcmcia_parse_tuple(&tuple, parse)) +				goto next_entry; + +		ret = loop_tuple(&tuple, parse, priv_data); +		if (!ret) +			break; + +next_entry: +		ret = pccard_get_next_tuple(s, function, &tuple); +	} + +	kfree(buf); +	return ret; +} +EXPORT_SYMBOL(pccard_loop_tuple); + +  /*======================================================================      This tries to determine if a card has a sensible CIS.  It returns diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 698d75cda08..790af87a922 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c @@ -61,17 +61,6 @@ INT_MODULE_PARM(unreset_limit,	30);		/* unreset_check's */  /* Access speed for attribute memory windows */  INT_MODULE_PARM(cis_speed,	300);		/* ns */ -#ifdef CONFIG_PCMCIA_DEBUG -static int pc_debug; - -module_param(pc_debug, int, 0644); - -int cs_debug_level(int level) -{ -	return pc_debug > level; -} -#endif -  socket_state_t dead_socket = {  	.csc_mask	= SS_DETECT, @@ -190,7 +179,7 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)  	if (!socket || !socket->ops || !socket->dev.parent || !socket->resource_ops)  		return -EINVAL; -	cs_dbg(socket, 0, "pcmcia_register_socket(0x%p)\n", socket->ops); +	dev_dbg(&socket->dev, "pcmcia_register_socket(0x%p)\n", socket->ops);  	spin_lock_init(&socket->lock); @@ -262,6 +251,13 @@ int pcmcia_register_socket(struct pcmcia_socket *socket)  	pcmcia_parse_events(socket, SS_DETECT); +	/* +	 * Let's try to get the PCMCIA module for 16-bit PCMCIA support. +	 * If it fails, it doesn't matter -- we still have 32-bit CardBus +	 * support to offer, so this is not a failure mode. +	 */ +	request_module_nowait("pcmcia"); +  	return 0;   err: @@ -282,7 +278,7 @@ void pcmcia_unregister_socket(struct pcmcia_socket *socket)  	if (!socket)  		return; -	cs_dbg(socket, 0, "pcmcia_unregister_socket(0x%p)\n", socket->ops); +	dev_dbg(&socket->dev, "pcmcia_unregister_socket(0x%p)\n", socket->ops);  	if (socket->thread)  		kthread_stop(socket->thread); @@ -335,7 +331,7 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)  	if (s->state & SOCKET_CARDBUS)  		return 0; -	cs_dbg(s, 1, "send_event(event %d, pri %d, callback 0x%p)\n", +	dev_dbg(&s->dev, "send_event(event %d, pri %d, callback 0x%p)\n",  	   event, priority, s->callback);  	if (!s->callback) @@ -352,7 +348,7 @@ static int send_event(struct pcmcia_socket *s, event_t event, int priority)  static void socket_remove_drivers(struct pcmcia_socket *skt)  { -	cs_dbg(skt, 4, "remove_drivers\n"); +	dev_dbg(&skt->dev, "remove_drivers\n");  	send_event(skt, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);  } @@ -361,7 +357,7 @@ static int socket_reset(struct pcmcia_socket *skt)  {  	int status, i; -	cs_dbg(skt, 4, "reset\n"); +	dev_dbg(&skt->dev, "reset\n");  	skt->socket.flags |= SS_OUTPUT_ENA | SS_RESET;  	skt->ops->set_socket(skt, &skt->socket); @@ -383,7 +379,7 @@ static int socket_reset(struct pcmcia_socket *skt)  		msleep(unreset_check * 10);  	} -	cs_err(skt, "time out after reset.\n"); +	dev_printk(KERN_ERR, &skt->dev, "time out after reset.\n");  	return -ETIMEDOUT;  } @@ -397,7 +393,7 @@ static void socket_shutdown(struct pcmcia_socket *s)  {  	int status; -	cs_dbg(s, 4, "shutdown\n"); +	dev_dbg(&s->dev, "shutdown\n");  	socket_remove_drivers(s);  	s->state &= SOCKET_INUSE | SOCKET_PRESENT; @@ -432,7 +428,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)  {  	int status, i; -	cs_dbg(skt, 4, "setup\n"); +	dev_dbg(&skt->dev, "setup\n");  	skt->ops->get_status(skt, &status);  	if (!(status & SS_DETECT)) @@ -452,13 +448,15 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)  	}  	if (status & SS_PENDING) { -		cs_err(skt, "voltage interrogation timed out.\n"); +		dev_printk(KERN_ERR, &skt->dev, +			   "voltage interrogation timed out.\n");  		return -ETIMEDOUT;  	}  	if (status & SS_CARDBUS) {  		if (!(skt->features & SS_CAP_CARDBUS)) { -			cs_err(skt, "cardbus cards are not supported.\n"); +			dev_printk(KERN_ERR, &skt->dev, +				"cardbus cards are not supported.\n");  			return -EINVAL;  		}  		skt->state |= SOCKET_CARDBUS; @@ -472,7 +470,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)  	else if (!(status & SS_XVCARD))  		skt->socket.Vcc = skt->socket.Vpp = 50;  	else { -		cs_err(skt, "unsupported voltage key.\n"); +		dev_printk(KERN_ERR, &skt->dev, "unsupported voltage key.\n");  		return -EIO;  	} @@ -489,7 +487,7 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)  	skt->ops->get_status(skt, &status);  	if (!(status & SS_POWERON)) { -		cs_err(skt, "unable to apply power.\n"); +		dev_printk(KERN_ERR, &skt->dev, "unable to apply power.\n");  		return -EIO;  	} @@ -509,7 +507,7 @@ static int socket_insert(struct pcmcia_socket *skt)  {  	int ret; -	cs_dbg(skt, 4, "insert\n"); +	dev_dbg(&skt->dev, "insert\n");  	if (!cs_socket_get(skt))  		return -ENODEV; @@ -529,7 +527,7 @@ static int socket_insert(struct pcmcia_socket *skt)  			skt->state |= SOCKET_CARDBUS_CONFIG;  		}  #endif -		cs_dbg(skt, 4, "insert done\n"); +		dev_dbg(&skt->dev, "insert done\n");  		send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);  	} else { @@ -576,7 +574,7 @@ static int socket_late_resume(struct pcmcia_socket *skt)  		 * FIXME: need a better check here for cardbus cards.  		 */  		if (verify_cis_cache(skt) != 0) { -			cs_dbg(skt, 4, "cis mismatch - different card\n"); +			dev_dbg(&skt->dev, "cis mismatch - different card\n");  			socket_remove_drivers(skt);  			destroy_cis_cache(skt);  			/* @@ -587,7 +585,7 @@ static int socket_late_resume(struct pcmcia_socket *skt)  			msleep(200);  			send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);  		} else { -			cs_dbg(skt, 4, "cis matches cache\n"); +			dev_dbg(&skt->dev, "cis matches cache\n");  			send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);  		}  	} else { @@ -723,7 +721,7 @@ static int pccardd(void *__skt)  void pcmcia_parse_events(struct pcmcia_socket *s, u_int events)  {  	unsigned long flags; -	cs_dbg(s, 4, "parse_events: events %08x\n", events); +	dev_dbg(&s->dev, "parse_events: events %08x\n", events);  	if (s->thread) {  		spin_lock_irqsave(&s->thread_lock, flags);  		s->thread_events |= events; @@ -773,19 +771,22 @@ int pcmcia_reset_card(struct pcmcia_socket *skt)  {  	int ret; -	cs_dbg(skt, 1, "resetting socket\n"); +	dev_dbg(&skt->dev, "resetting socket\n");  	mutex_lock(&skt->skt_mutex);  	do {  		if (!(skt->state & SOCKET_PRESENT)) { +			dev_dbg(&skt->dev, "can't reset, not present\n");  			ret = -ENODEV;  			break;  		}  		if (skt->state & SOCKET_SUSPEND) { +			dev_dbg(&skt->dev, "can't reset, suspended\n");  			ret = -EBUSY;  			break;  		}  		if (skt->state & SOCKET_CARDBUS) { +			dev_dbg(&skt->dev, "can't reset, is cardbus\n");  			ret = -EPERM;  			break;  		} @@ -818,7 +819,7 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)  {  	int ret; -	cs_dbg(skt, 1, "suspending socket\n"); +	dev_dbg(&skt->dev, "suspending socket\n");  	mutex_lock(&skt->skt_mutex);  	do { @@ -848,7 +849,7 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)  {  	int ret; -	cs_dbg(skt, 1, "waking up socket\n"); +	dev_dbg(&skt->dev, "waking up socket\n");  	mutex_lock(&skt->skt_mutex);  	do { @@ -876,7 +877,7 @@ int pcmcia_eject_card(struct pcmcia_socket *skt)  {  	int ret; -	cs_dbg(skt, 1, "user eject request\n"); +	dev_dbg(&skt->dev, "user eject request\n");  	mutex_lock(&skt->skt_mutex);  	do { @@ -905,7 +906,7 @@ int pcmcia_insert_card(struct pcmcia_socket *skt)  {  	int ret; -	cs_dbg(skt, 1, "user insert request\n"); +	dev_dbg(&skt->dev, "user insert request\n");  	mutex_lock(&skt->skt_mutex);  	do { diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h index 1f4098f1354..3bc02d53a3a 100644 --- a/drivers/pcmcia/cs_internal.h +++ b/drivers/pcmcia/cs_internal.h @@ -107,28 +107,6 @@ static inline void cs_socket_put(struct pcmcia_socket *skt)  	}  } -#ifdef CONFIG_PCMCIA_DEBUG -extern int cs_debug_level(int); - -#define cs_dbg(skt, lvl, fmt, arg...) do {		\ -	if (cs_debug_level(lvl))			\ -		dev_printk(KERN_DEBUG, &skt->dev,	\ -		 "cs: " fmt, ## arg);			\ -} while (0) -#define __cs_dbg(lvl, fmt, arg...) do {			\ -	if (cs_debug_level(lvl))			\ -		printk(KERN_DEBUG 			\ -		 "cs: " fmt, ## arg);			\ -} while (0) - -#else -#define cs_dbg(skt, lvl, fmt, arg...) do { } while (0) -#define __cs_dbg(lvl, fmt, arg...) do { } while (0) -#endif - -#define cs_err(skt, fmt, arg...) \ -	dev_printk(KERN_ERR, &skt->dev, "cs: " fmt, ## arg) -  /*   * Stuff internal to module "pcmcia_core": @@ -170,10 +148,6 @@ extern struct rw_semaphore pcmcia_socket_list_rwsem;  extern struct list_head pcmcia_socket_list;  extern struct class pcmcia_socket_class; -int pcmcia_get_window(struct pcmcia_socket *s, -		      window_handle_t *handle, -		      int idx, -		      win_req_t *req);  int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);  struct pcmcia_socket *pcmcia_get_socket_by_nr(unsigned int nr); @@ -199,6 +173,22 @@ int pcmcia_replace_cis(struct pcmcia_socket *s,  		       const u8 *data, const size_t len);  int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count); +/* loop over CIS entries */ +int pccard_loop_tuple(struct pcmcia_socket *s, unsigned int function, +		      cisdata_t code, cisparse_t *parse, void *priv_data, +		      int (*loop_tuple) (tuple_t *tuple, +					 cisparse_t *parse, +					 void *priv_data)); + +int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, +			tuple_t *tuple); + +int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, +			tuple_t *tuple); + +int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); + +  /* rsrc_mgr.c */  int pcmcia_validate_mem(struct pcmcia_socket *s);  struct resource *pcmcia_find_io_region(unsigned long base, diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index f5b7079f13d..05893d41dd4 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c @@ -41,129 +41,11 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");  MODULE_DESCRIPTION("PCMCIA Driver Services");  MODULE_LICENSE("GPL"); -#ifdef CONFIG_PCMCIA_DEBUG -int ds_pc_debug; - -module_param_named(pc_debug, ds_pc_debug, int, 0644); - -#define ds_dbg(lvl, fmt, arg...) do {				\ -	if (ds_pc_debug > (lvl))				\ -		printk(KERN_DEBUG "ds: " fmt , ## arg);		\ -} while (0) -#define ds_dev_dbg(lvl, dev, fmt, arg...) do {				\ -	if (ds_pc_debug > (lvl))					\ -		dev_printk(KERN_DEBUG, dev, "ds: " fmt , ## arg);	\ -} while (0) -#else -#define ds_dbg(lvl, fmt, arg...) do { } while (0) -#define ds_dev_dbg(lvl, dev, fmt, arg...) do { } while (0) -#endif  spinlock_t pcmcia_dev_list_lock;  /*====================================================================*/ -/* code which was in cs.c before */ - -/* String tables for error messages */ - -typedef struct lookup_t { -    const int key; -    const char *msg; -} lookup_t; - -static const lookup_t error_table[] = { -    { 0,			"Operation succeeded" }, -    { -EIO,			"Input/Output error" }, -    { -ENODEV,			"No card present" }, -    { -EINVAL,			"Bad parameter" }, -    { -EACCES,			"Configuration locked" }, -    { -EBUSY,			"Resource in use" }, -    { -ENOSPC,			"No more items" }, -    { -ENOMEM,			"Out of resource" }, -}; - - -static const lookup_t service_table[] = { -    { AccessConfigurationRegister,	"AccessConfigurationRegister" }, -    { AddSocketServices,		"AddSocketServices" }, -    { AdjustResourceInfo,		"AdjustResourceInfo" }, -    { CheckEraseQueue,			"CheckEraseQueue" }, -    { CloseMemory,			"CloseMemory" }, -    { DeregisterClient,			"DeregisterClient" }, -    { DeregisterEraseQueue,		"DeregisterEraseQueue" }, -    { GetCardServicesInfo,		"GetCardServicesInfo" }, -    { GetClientInfo,			"GetClientInfo" }, -    { GetConfigurationInfo,		"GetConfigurationInfo" }, -    { GetEventMask,			"GetEventMask" }, -    { GetFirstClient,			"GetFirstClient" }, -    { GetFirstRegion,			"GetFirstRegion" }, -    { GetFirstTuple,			"GetFirstTuple" }, -    { GetNextClient,			"GetNextClient" }, -    { GetNextRegion,			"GetNextRegion" }, -    { GetNextTuple,			"GetNextTuple" }, -    { GetStatus,			"GetStatus" }, -    { GetTupleData,			"GetTupleData" }, -    { MapMemPage,			"MapMemPage" }, -    { ModifyConfiguration,		"ModifyConfiguration" }, -    { ModifyWindow,			"ModifyWindow" }, -    { OpenMemory,			"OpenMemory" }, -    { ParseTuple,			"ParseTuple" }, -    { ReadMemory,			"ReadMemory" }, -    { RegisterClient,			"RegisterClient" }, -    { RegisterEraseQueue,		"RegisterEraseQueue" }, -    { RegisterMTD,			"RegisterMTD" }, -    { ReleaseConfiguration,		"ReleaseConfiguration" }, -    { ReleaseIO,			"ReleaseIO" }, -    { ReleaseIRQ,			"ReleaseIRQ" }, -    { ReleaseWindow,			"ReleaseWindow" }, -    { RequestConfiguration,		"RequestConfiguration" }, -    { RequestIO,			"RequestIO" }, -    { RequestIRQ,			"RequestIRQ" }, -    { RequestSocketMask,		"RequestSocketMask" }, -    { RequestWindow,			"RequestWindow" }, -    { ResetCard,			"ResetCard" }, -    { SetEventMask,			"SetEventMask" }, -    { ValidateCIS,			"ValidateCIS" }, -    { WriteMemory,			"WriteMemory" }, -    { BindDevice,			"BindDevice" }, -    { BindMTD,				"BindMTD" }, -    { ReportError,			"ReportError" }, -    { SuspendCard,			"SuspendCard" }, -    { ResumeCard,			"ResumeCard" }, -    { EjectCard,			"EjectCard" }, -    { InsertCard,			"InsertCard" }, -    { ReplaceCIS,			"ReplaceCIS" } -}; - -const char *pcmcia_error_func(int func) -{ -	int i; - -	for (i = 0; i < ARRAY_SIZE(service_table); i++) -		if (service_table[i].key == func) -			return service_table[i].msg; - -	return "Unknown service number"; -} -EXPORT_SYMBOL(pcmcia_error_func); - -const char *pcmcia_error_ret(int ret) -{ -	int i; - -	for (i = 0; i < ARRAY_SIZE(error_table); i++) -		if (error_table[i].key == ret) -			return error_table[i].msg; - -	return "unknown"; -} -EXPORT_SYMBOL(pcmcia_error_ret); - -/*======================================================================*/ - - -  static void pcmcia_check_driver(struct pcmcia_driver *p_drv)  {  	struct pcmcia_device_id *did = p_drv->id_table; @@ -303,7 +185,7 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)  	spin_lock_init(&driver->dynids.lock);  	INIT_LIST_HEAD(&driver->dynids.list); -	ds_dbg(3, "registering driver %s\n", driver->drv.name); +	pr_debug("registering driver %s\n", driver->drv.name);  	error = driver_register(&driver->drv);  	if (error < 0) @@ -323,7 +205,7 @@ EXPORT_SYMBOL(pcmcia_register_driver);   */  void pcmcia_unregister_driver(struct pcmcia_driver *driver)  { -	ds_dbg(3, "unregistering driver %s\n", driver->drv.name); +	pr_debug("unregistering driver %s\n", driver->drv.name);  	driver_unregister(&driver->drv);  	pcmcia_free_dynids(driver);  } @@ -350,14 +232,14 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev)  static void pcmcia_release_function(struct kref *ref)  {  	struct config_t *c = container_of(ref, struct config_t, ref); -	ds_dbg(1, "releasing config_t\n"); +	pr_debug("releasing config_t\n");  	kfree(c);  }  static void pcmcia_release_dev(struct device *dev)  {  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev); -	ds_dev_dbg(1, dev, "releasing device\n"); +	dev_dbg(dev, "releasing device\n");  	pcmcia_put_socket(p_dev->socket);  	kfree(p_dev->devname);  	kref_put(&p_dev->function_config->ref, pcmcia_release_function); @@ -367,7 +249,7 @@ static void pcmcia_release_dev(struct device *dev)  static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc)  {  	if (!s->pcmcia_state.device_add_pending) { -		ds_dev_dbg(1, &s->dev, "scheduling to add %s secondary" +		dev_dbg(&s->dev, "scheduling to add %s secondary"  		       " device to %d\n", mfc ? "mfc" : "pfc", s->sock);  		s->pcmcia_state.device_add_pending = 1;  		s->pcmcia_state.mfc_pfc = mfc; @@ -405,7 +287,7 @@ static int pcmcia_device_probe(struct device * dev)  	 */  	did = dev_get_drvdata(&p_dev->dev); -	ds_dev_dbg(1, dev, "trying to bind to %s\n", p_drv->drv.name); +	dev_dbg(dev, "trying to bind to %s\n", p_drv->drv.name);  	if ((!p_drv->probe) || (!p_dev->function_config) ||  	    (!try_module_get(p_drv->owner))) { @@ -428,7 +310,7 @@ static int pcmcia_device_probe(struct device * dev)  	ret = p_drv->probe(p_dev);  	if (ret) { -		ds_dev_dbg(1, dev, "binding to %s failed with %d\n", +		dev_dbg(dev, "binding to %s failed with %d\n",  			   p_drv->drv.name, ret);  		goto put_module;  	} @@ -456,7 +338,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le  	struct pcmcia_device	*tmp;  	unsigned long		flags; -	ds_dev_dbg(2, leftover ? &leftover->dev : &s->dev, +	dev_dbg(leftover ? &leftover->dev : &s->dev,  		   "pcmcia_card_remove(%d) %s\n", s->sock,  		   leftover ? leftover->devname : ""); @@ -475,7 +357,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le  		p_dev->_removed=1;  		spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags); -		ds_dev_dbg(2, &p_dev->dev, "unregistering device\n"); +		dev_dbg(&p_dev->dev, "unregistering device\n");  		device_unregister(&p_dev->dev);  	} @@ -492,7 +374,7 @@ static int pcmcia_device_remove(struct device * dev)  	p_dev = to_pcmcia_dev(dev);  	p_drv = to_pcmcia_drv(dev->driver); -	ds_dev_dbg(1, dev, "removing device\n"); +	dev_dbg(dev, "removing device\n");  	/* If we're removing the primary module driving a  	 * pseudo multi-function card, we need to unbind @@ -572,7 +454,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)  		}  		if (!pccard_read_tuple(p_dev->socket, p_dev->func,  				      CISTPL_DEVICE_GEO, devgeo)) { -			ds_dev_dbg(0, &p_dev->dev, +			dev_dbg(&p_dev->dev,  				   "mem device geometry probably means "  				   "FUNCID_MEMORY\n");  			p_dev->func_id = CISTPL_FUNCID_MEMORY; @@ -628,7 +510,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f  	mutex_lock(&device_add_lock); -	ds_dbg(3, "adding device to %d, function %d\n", s->sock, function); +	pr_debug("adding device to %d, function %d\n", s->sock, function);  	/* max of 4 devices per card */  	if (s->device_count == 4) @@ -654,7 +536,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f  	p_dev->devname = kasprintf(GFP_KERNEL, "pcmcia%s", dev_name(&p_dev->dev));  	if (!p_dev->devname)  		goto err_free; -	ds_dev_dbg(3, &p_dev->dev, "devname is %s\n", p_dev->devname); +	dev_dbg(&p_dev->dev, "devname is %s\n", p_dev->devname);  	spin_lock_irqsave(&pcmcia_dev_list_lock, flags); @@ -677,7 +559,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f  	spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);  	if (!p_dev->function_config) { -		ds_dev_dbg(3, &p_dev->dev, "creating config_t\n"); +		dev_dbg(&p_dev->dev, "creating config_t\n");  		p_dev->function_config = kzalloc(sizeof(struct config_t),  						 GFP_KERNEL);  		if (!p_dev->function_config) @@ -722,20 +604,20 @@ static int pcmcia_card_add(struct pcmcia_socket *s)  	int ret = 0;  	if (!(s->resource_setup_done)) { -		ds_dev_dbg(3, &s->dev, +		dev_dbg(&s->dev,  			   "no resources available, delaying card_add\n");  		return -EAGAIN; /* try again, but later... */  	}  	if (pcmcia_validate_mem(s)) { -		ds_dev_dbg(3, &s->dev, "validating mem resources failed, " +		dev_dbg(&s->dev, "validating mem resources failed, "  		       "delaying card_add\n");  		return -EAGAIN; /* try again, but later... */  	}  	ret = pccard_validate_cis(s, &no_chains);  	if (ret || !no_chains) { -		ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n"); +		dev_dbg(&s->dev, "invalid CIS or invalid resources\n");  		return -ENODEV;  	} @@ -756,7 +638,7 @@ static void pcmcia_delayed_add_device(struct work_struct *work)  {  	struct pcmcia_socket *s =  		container_of(work, struct pcmcia_socket, device_add); -	ds_dev_dbg(1, &s->dev, "adding additional device to %d\n", s->sock); +	dev_dbg(&s->dev, "adding additional device to %d\n", s->sock);  	pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);  	s->pcmcia_state.device_add_pending = 0;  	s->pcmcia_state.mfc_pfc = 0; @@ -766,7 +648,7 @@ static int pcmcia_requery(struct device *dev, void * _data)  {  	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);  	if (!p_dev->dev.driver) { -		ds_dev_dbg(1, dev, "update device information\n"); +		dev_dbg(dev, "update device information\n");  		pcmcia_device_query(p_dev);  	} @@ -780,7 +662,7 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis)  	unsigned long flags;  	/* must be called with skt_mutex held */ -	ds_dev_dbg(0, &skt->dev, "re-scanning socket %d\n", skt->sock); +	dev_dbg(&skt->dev, "re-scanning socket %d\n", skt->sock);  	spin_lock_irqsave(&pcmcia_dev_list_lock, flags);  	if (list_empty(&skt->devices_list)) @@ -835,7 +717,7 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)  	if (!filename)  		return -EINVAL; -	ds_dev_dbg(1, &dev->dev, "trying to load CIS file %s\n", filename); +	dev_dbg(&dev->dev, "trying to load CIS file %s\n", filename);  	if (request_firmware(&fw, filename, &dev->dev) == 0) {  		if (fw->size >= CISTPL_MAX_CIS_SIZE) { @@ -953,14 +835,14 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,  		 * after it has re-checked that there is no possible module  		 * with a prod_id/manf_id/card_id match.  		 */ -		ds_dev_dbg(0, &dev->dev, +		dev_dbg(&dev->dev,  			"skipping FUNC_ID match until userspace interaction\n");  		if (!dev->allow_func_id_match)  			return 0;  	}  	if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) { -		ds_dev_dbg(0, &dev->dev, "device needs a fake CIS\n"); +		dev_dbg(&dev->dev, "device needs a fake CIS\n");  		if (!dev->socket->fake_cis)  			pcmcia_load_firmware(dev, did->cisfile); @@ -992,9 +874,9 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {  	/* match dynamic devices first */  	spin_lock(&p_drv->dynids.lock);  	list_for_each_entry(dynid, &p_drv->dynids.list, node) { -		ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name); +		dev_dbg(dev, "trying to match to %s\n", drv->name);  		if (pcmcia_devmatch(p_dev, &dynid->id)) { -			ds_dev_dbg(0, dev, "matched to %s\n", drv->name); +			dev_dbg(dev, "matched to %s\n", drv->name);  			spin_unlock(&p_drv->dynids.lock);  			return 1;  		} @@ -1004,15 +886,15 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {  #ifdef CONFIG_PCMCIA_IOCTL  	/* matching by cardmgr */  	if (p_dev->cardmgr == p_drv) { -		ds_dev_dbg(0, dev, "cardmgr matched to %s\n", drv->name); +		dev_dbg(dev, "cardmgr matched to %s\n", drv->name);  		return 1;  	}  #endif  	while (did && did->match_flags) { -		ds_dev_dbg(3, dev, "trying to match to %s\n", drv->name); +		dev_dbg(dev, "trying to match to %s\n", drv->name);  		if (pcmcia_devmatch(p_dev, did)) { -			ds_dev_dbg(0, dev, "matched to %s\n", drv->name); +			dev_dbg(dev, "matched to %s\n", drv->name);  			return 1;  		}  		did++; @@ -1218,7 +1100,7 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)  	if (p_dev->suspended)  		return 0; -	ds_dev_dbg(2, dev, "suspending\n"); +	dev_dbg(dev, "suspending\n");  	if (dev->driver)  		p_drv = to_pcmcia_drv(dev->driver); @@ -1238,7 +1120,7 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)  	}  	if (p_dev->device_no == p_dev->func) { -		ds_dev_dbg(2, dev, "releasing configuration\n"); +		dev_dbg(dev, "releasing configuration\n");  		pcmcia_release_configuration(p_dev);  	} @@ -1258,7 +1140,7 @@ static int pcmcia_dev_resume(struct device * dev)  	if (!p_dev->suspended)  		return 0; -	ds_dev_dbg(2, dev, "resuming\n"); +	dev_dbg(dev, "resuming\n");  	if (dev->driver)  		p_drv = to_pcmcia_drv(dev->driver); @@ -1267,7 +1149,7 @@ static int pcmcia_dev_resume(struct device * dev)  		goto out;  	if (p_dev->device_no == p_dev->func) { -		ds_dev_dbg(2, dev, "requesting configuration\n"); +		dev_dbg(dev, "requesting configuration\n");  		ret = pcmcia_request_configuration(p_dev, &p_dev->conf);  		if (ret)  			goto out; @@ -1309,14 +1191,14 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)  static int pcmcia_bus_resume(struct pcmcia_socket *skt)  { -	ds_dev_dbg(2, &skt->dev, "resuming socket %d\n", skt->sock); +	dev_dbg(&skt->dev, "resuming socket %d\n", skt->sock);  	bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);  	return 0;  }  static int pcmcia_bus_suspend(struct pcmcia_socket *skt)  { -	ds_dev_dbg(2, &skt->dev, "suspending socket %d\n", skt->sock); +	dev_dbg(&skt->dev, "suspending socket %d\n", skt->sock);  	if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,  			     pcmcia_bus_suspend_callback)) {  		pcmcia_bus_resume(skt); @@ -1348,7 +1230,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)  		return -ENODEV;  	} -	ds_dev_dbg(1, &skt->dev, "ds_event(0x%06x, %d, 0x%p)\n", +	dev_dbg(&skt->dev, "ds_event(0x%06x, %d, 0x%p)\n",  		   event, priority, skt);  	switch (event) { diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index a4aacb830b8..c13fd936051 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -63,21 +63,6 @@  #include "vg468.h"  #include "ricoh.h" -#ifdef CONFIG_PCMCIA_DEBUG -static const char version[] = -"i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)"; - -static int pc_debug; - -module_param(pc_debug, int, 0644); - -#define debug(lvl, fmt, arg...) do {				\ -	if (pc_debug > (lvl))					\ -		printk(KERN_DEBUG "i82365: " fmt , ## arg);	\ -} while (0) -#else -#define debug(lvl, fmt, arg...) do { } while (0) -#endif  static irqreturn_t i365_count_irq(int, void *);  static inline int _check_irq(int irq, int flags) @@ -501,13 +486,13 @@ static irqreturn_t i365_count_irq(int irq, void *dev)  {      i365_get(irq_sock, I365_CSC);      irq_hits++; -    debug(2, "-> hit on irq %d\n", irq); +    pr_debug("i82365: -> hit on irq %d\n", irq);      return IRQ_HANDLED;  }  static u_int __init test_irq(u_short sock, int irq)  { -    debug(2, "  testing ISA irq %d\n", irq); +    pr_debug("i82365:  testing ISA irq %d\n", irq);      if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan",  			i365_count_irq) != 0)  	return 1; @@ -515,7 +500,7 @@ static u_int __init test_irq(u_short sock, int irq)      msleep(10);      if (irq_hits) {  	free_irq(irq, i365_count_irq); -	debug(2, "    spurious hit!\n"); +	pr_debug("i82365:    spurious hit!\n");  	return 1;      } @@ -528,7 +513,7 @@ static u_int __init test_irq(u_short sock, int irq)      /* mask all interrupts */      i365_set(sock, I365_CSCINT, 0); -    debug(2, "    hits = %d\n", irq_hits); +    pr_debug("i82365:    hits = %d\n", irq_hits);      return (irq_hits != 1);  } @@ -854,7 +839,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev)      u_long flags = 0;      int handled = 0; -    debug(4, "pcic_interrupt(%d)\n", irq); +    pr_debug("pcic_interrupt(%d)\n", irq);      for (j = 0; j < 20; j++) {  	active = 0; @@ -878,7 +863,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev)  		events |= (csc & I365_CSC_READY) ? SS_READY : 0;  	    }  	    ISA_UNLOCK(i, flags); -	    debug(2, "socket %d event 0x%02x\n", i, events); +	    pr_debug("socket %d event 0x%02x\n", i, events);  	    if (events)  		pcmcia_parse_events(&socket[i].socket, events); @@ -890,7 +875,7 @@ static irqreturn_t pcic_interrupt(int irq, void *dev)      if (j == 20)  	printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n"); -    debug(4, "interrupt done\n"); +    pr_debug("pcic_interrupt done\n");      return IRQ_RETVAL(handled);  } /* pcic_interrupt */ @@ -932,7 +917,7 @@ static int i365_get_status(u_short sock, u_int *value)  	}      } -    debug(1, "GetStatus(%d) = %#4.4x\n", sock, *value); +    pr_debug("GetStatus(%d) = %#4.4x\n", sock, *value);      return 0;  } /* i365_get_status */ @@ -943,7 +928,7 @@ static int i365_set_socket(u_short sock, socket_state_t *state)      struct i82365_socket *t = &socket[sock];      u_char reg; -    debug(1, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " +    pr_debug("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "  	  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,  	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask); @@ -1052,7 +1037,7 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io)  {      u_char map, ioctl; -    debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, " +    pr_debug("SetIOMap(%d, %d, %#2.2x, %d ns, "  	  "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed,  	  (unsigned long long)io->start, (unsigned long long)io->stop);      map = io->map; @@ -1082,7 +1067,7 @@ static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)      u_short base, i;      u_char map; -    debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, " +    pr_debug("SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, "  	  "%#x)\n", sock, mem->map, mem->flags, mem->speed,  	  (unsigned long long)mem->res->start,  	  (unsigned long long)mem->res->end, mem->card_start); diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 7dfbee1dcd7..26a621c9e2f 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -38,17 +38,6 @@  #include "m32r_cfc.h" -#ifdef CONFIG_PCMCIA_DEBUG -static int m32r_cfc_debug; -module_param(m32r_cfc_debug, int, 0644); -#define debug(lvl, fmt, arg...) do {				\ -	if (m32r_cfc_debug > (lvl))				\ -		printk(KERN_DEBUG "m32r_cfc: " fmt , ## arg);	\ -} while (0) -#else -#define debug(n, args...) do { } while (0) -#endif -  /* Poll status interval -- 0 means default to interrupt */  static int poll_interval = 0; @@ -123,7 +112,7 @@ void pcc_ioread_byte(int sock, unsigned long port, void *buf, size_t size,  	unsigned char *bp = (unsigned char *)buf;  	unsigned long flags; -	debug(3, "m32r_cfc: pcc_ioread_byte: sock=%d, port=%#lx, buf=%p, " +	pr_debug("m32r_cfc: pcc_ioread_byte: sock=%d, port=%#lx, buf=%p, "  		 "size=%u, nmemb=%d, flag=%d\n",  		  sock, port, buf, size, nmemb, flag); @@ -132,7 +121,7 @@ void pcc_ioread_byte(int sock, unsigned long port, void *buf, size_t size,  		printk("m32r_cfc:ioread_byte null port :%#lx\n",port);  		return;  	} -	debug(3, "m32r_cfc: pcc_ioread_byte: addr=%#lx\n", addr); +	pr_debug("m32r_cfc: pcc_ioread_byte: addr=%#lx\n", addr);  	spin_lock_irqsave(&pcc_lock, flags);  	/* read Byte */ @@ -148,7 +137,7 @@ void pcc_ioread_word(int sock, unsigned long port, void *buf, size_t size,  	unsigned short *bp = (unsigned short *)buf;  	unsigned long flags; -	debug(3, "m32r_cfc: pcc_ioread_word: sock=%d, port=%#lx, " +	pr_debug("m32r_cfc: pcc_ioread_word: sock=%d, port=%#lx, "  		 "buf=%p, size=%u, nmemb=%d, flag=%d\n",  		 sock, port, buf, size, nmemb, flag); @@ -163,7 +152,7 @@ void pcc_ioread_word(int sock, unsigned long port, void *buf, size_t size,  		printk("m32r_cfc:ioread_word null port :%#lx\n",port);  		return;  	} -	debug(3, "m32r_cfc: pcc_ioread_word: addr=%#lx\n", addr); +	pr_debug("m32r_cfc: pcc_ioread_word: addr=%#lx\n", addr);  	spin_lock_irqsave(&pcc_lock, flags);  	/* read Word */ @@ -179,7 +168,7 @@ void pcc_iowrite_byte(int sock, unsigned long port, void *buf, size_t size,  	unsigned char *bp = (unsigned char *)buf;  	unsigned long flags; -	debug(3, "m32r_cfc: pcc_iowrite_byte: sock=%d, port=%#lx, " +	pr_debug("m32r_cfc: pcc_iowrite_byte: sock=%d, port=%#lx, "  		 "buf=%p, size=%u, nmemb=%d, flag=%d\n",  		 sock, port, buf, size, nmemb, flag); @@ -189,7 +178,7 @@ void pcc_iowrite_byte(int sock, unsigned long port, void *buf, size_t size,  		printk("m32r_cfc:iowrite_byte null port:%#lx\n",port);  		return;  	} -	debug(3, "m32r_cfc: pcc_iowrite_byte: addr=%#lx\n", addr); +	pr_debug("m32r_cfc: pcc_iowrite_byte: addr=%#lx\n", addr);  	spin_lock_irqsave(&pcc_lock, flags);  	while (nmemb--) @@ -204,7 +193,7 @@ void pcc_iowrite_word(int sock, unsigned long port, void *buf, size_t size,  	unsigned short *bp = (unsigned short *)buf;  	unsigned long flags; -	debug(3, "m32r_cfc: pcc_iowrite_word: sock=%d, port=%#lx, " +	pr_debug("m32r_cfc: pcc_iowrite_word: sock=%d, port=%#lx, "  		 "buf=%p, size=%u, nmemb=%d, flag=%d\n",  		 sock, port, buf, size, nmemb, flag); @@ -226,7 +215,7 @@ void pcc_iowrite_word(int sock, unsigned long port, void *buf, size_t size,  		return;  	}  #endif -	debug(3, "m32r_cfc: pcc_iowrite_word: addr=%#lx\n", addr); +	pr_debug("m32r_cfc: pcc_iowrite_word: addr=%#lx\n", addr);  	spin_lock_irqsave(&pcc_lock, flags);  	while (nmemb--) @@ -262,7 +251,7 @@ static struct timer_list poll_timer;  static unsigned int pcc_get(u_short sock, unsigned int reg)  {  	unsigned int val = inw(reg); -	debug(3, "m32r_cfc: pcc_get: reg(0x%08x)=0x%04x\n", reg, val); +	pr_debug("m32r_cfc: pcc_get: reg(0x%08x)=0x%04x\n", reg, val);  	return val;  } @@ -270,7 +259,7 @@ static unsigned int pcc_get(u_short sock, unsigned int reg)  static void pcc_set(u_short sock, unsigned int reg, unsigned int data)  {  	outw(data, reg); -	debug(3, "m32r_cfc: pcc_set: reg(0x%08x)=0x%04x\n", reg, data); +	pr_debug("m32r_cfc: pcc_set: reg(0x%08x)=0x%04x\n", reg, data);  }  /*====================================================================== @@ -286,14 +275,14 @@ static int __init is_alive(u_short sock)  {  	unsigned int stat; -	debug(3, "m32r_cfc: is_alive:\n"); +	pr_debug("m32r_cfc: is_alive:\n");  	printk("CF: ");  	stat = pcc_get(sock, (unsigned int)PLD_CFSTS);  	if (!stat)  		printk("No ");  	printk("Card is detected at socket %d : stat = 0x%08x\n", sock, stat); -	debug(3, "m32r_cfc: is_alive: sock stat is 0x%04x\n", stat); +	pr_debug("m32r_cfc: is_alive: sock stat is 0x%04x\n", stat);  	return 0;  } @@ -303,7 +292,7 @@ static void add_pcc_socket(ulong base, int irq, ulong mapaddr,  {  	pcc_socket_t *t = &socket[pcc_sockets]; -	debug(3, "m32r_cfc: add_pcc_socket: base=%#lx, irq=%d, " +	pr_debug("m32r_cfc: add_pcc_socket: base=%#lx, irq=%d, "  		 "mapaddr=%#lx, ioaddr=%08x\n",  		 base, irq, mapaddr, ioaddr); @@ -358,7 +347,7 @@ static void add_pcc_socket(ulong base, int irq, ulong mapaddr,  	/* eject interrupt */  	request_irq(irq+1, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);  #endif -	debug(3, "m32r_cfc: enable CFMSK, RDYSEL\n"); +	pr_debug("m32r_cfc: enable CFMSK, RDYSEL\n");  	pcc_set(pcc_sockets, (unsigned int)PLD_CFIMASK, 0x01);  #endif	/* CONFIG_PLAT_USRV */  #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) @@ -378,26 +367,26 @@ static irqreturn_t pcc_interrupt(int irq, void *dev)  	u_int events = 0;  	int handled = 0; -	debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p\n", irq, dev); +	pr_debug("m32r_cfc: pcc_interrupt: irq=%d, dev=%p\n", irq, dev);  	for (i = 0; i < pcc_sockets; i++) {  		if (socket[i].cs_irq1 != irq && socket[i].cs_irq2 != irq)  			continue;  		handled = 1; -		debug(3, "m32r_cfc: pcc_interrupt: socket %d irq 0x%02x ", +		pr_debug("m32r_cfc: pcc_interrupt: socket %d irq 0x%02x ",  			i, irq);  		events |= SS_DETECT;	/* insert or eject */  		if (events)  			pcmcia_parse_events(&socket[i].socket, events);  	} -	debug(3, "m32r_cfc: pcc_interrupt: done\n"); +	pr_debug("m32r_cfc: pcc_interrupt: done\n");  	return IRQ_RETVAL(handled);  } /* pcc_interrupt */  static void pcc_interrupt_wrapper(u_long data)  { -	debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n"); +	pr_debug("m32r_cfc: pcc_interrupt_wrapper:\n");  	pcc_interrupt(0, NULL);  	init_timer(&poll_timer);  	poll_timer.expires = jiffies + poll_interval; @@ -410,17 +399,17 @@ static int _pcc_get_status(u_short sock, u_int *value)  {  	u_int status; -	debug(3, "m32r_cfc: _pcc_get_status:\n"); +	pr_debug("m32r_cfc: _pcc_get_status:\n");  	status = pcc_get(sock, (unsigned int)PLD_CFSTS);  	*value = (status) ? SS_DETECT : 0; - 	debug(3, "m32r_cfc: _pcc_get_status: status=0x%08x\n", status); +	pr_debug("m32r_cfc: _pcc_get_status: status=0x%08x\n", status);  #if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)  	if ( status ) {  		/* enable CF power */  		status = inw((unsigned int)PLD_CPCR);  		if (!(status & PLD_CPCR_CF)) { -			debug(3, "m32r_cfc: _pcc_get_status: " +			pr_debug("m32r_cfc: _pcc_get_status: "  				 "power on (CPCR=0x%08x)\n", status);  			status |= PLD_CPCR_CF;  			outw(status, (unsigned int)PLD_CPCR); @@ -439,7 +428,7 @@ static int _pcc_get_status(u_short sock, u_int *value)  		status &= ~PLD_CPCR_CF;  		outw(status, (unsigned int)PLD_CPCR);  		udelay(100); -		debug(3, "m32r_cfc: _pcc_get_status: " +		pr_debug("m32r_cfc: _pcc_get_status: "  			 "power off (CPCR=0x%08x)\n", status);  	}  #elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3) @@ -465,13 +454,13 @@ static int _pcc_get_status(u_short sock, u_int *value)  		/* disable CF power */  	        pcc_set(sock, (unsigned int)PLD_CPCR, 0);  		udelay(100); -		debug(3, "m32r_cfc: _pcc_get_status: " +		pr_debug("m32r_cfc: _pcc_get_status: "  			 "power off (CPCR=0x%08x)\n", status);  	}  #else  #error no platform configuration  #endif -	debug(3, "m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n", +	pr_debug("m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n",  		 sock, *value);  	return 0;  } /* _get_status */ @@ -480,7 +469,7 @@ static int _pcc_get_status(u_short sock, u_int *value)  static int _pcc_set_socket(u_short sock, socket_state_t *state)  { -	debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " +	pr_debug("m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "  		  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,  		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask); @@ -492,41 +481,39 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)  	}  #endif  	if (state->flags & SS_RESET) { -		debug(3, ":RESET\n"); +		pr_debug(":RESET\n");  		pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);  	}else{  		pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x100);  	}  	if (state->flags & SS_OUTPUT_ENA){ -		debug(3, ":OUTPUT_ENA\n"); +		pr_debug(":OUTPUT_ENA\n");  		/* bit clear */  		pcc_set(sock,(unsigned int)PLD_CFBUFCR,0);  	} else {  		pcc_set(sock,(unsigned int)PLD_CFBUFCR,1);  	} -#ifdef CONFIG_PCMCIA_DEBUG  	if(state->flags & SS_IOCARD){ -		debug(3, ":IOCARD"); +		pr_debug(":IOCARD");  	}  	if (state->flags & SS_PWR_AUTO) { -		debug(3, ":PWR_AUTO"); +		pr_debug(":PWR_AUTO");  	}  	if (state->csc_mask & SS_DETECT) -		debug(3, ":csc-SS_DETECT"); +		pr_debug(":csc-SS_DETECT");  	if (state->flags & SS_IOCARD) {  		if (state->csc_mask & SS_STSCHG) -			debug(3, ":STSCHG"); +			pr_debug(":STSCHG");  	} else {  		if (state->csc_mask & SS_BATDEAD) -			debug(3, ":BATDEAD"); +			pr_debug(":BATDEAD");  		if (state->csc_mask & SS_BATWARN) -			debug(3, ":BATWARN"); +			pr_debug(":BATWARN");  		if (state->csc_mask & SS_READY) -			debug(3, ":READY"); +			pr_debug(":READY");  	} -	debug(3, "\n"); -#endif +	pr_debug("\n");  	return 0;  } /* _set_socket */ @@ -536,7 +523,7 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)  {  	u_char map; -	debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, "  		  "%#llx-%#llx)\n", sock, io->map, io->flags,  		  io->speed, (unsigned long long)io->start,  		  (unsigned long long)io->stop); @@ -554,7 +541,7 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)  	u_long addr;  	pcc_socket_t *t = &socket[sock]; -	debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, "  		 "%#llx, %#x)\n", sock, map, mem->flags,  		 mem->speed, (unsigned long long)mem->static_start,  		 mem->card_start); @@ -640,11 +627,11 @@ static int pcc_get_status(struct pcmcia_socket *s, u_int *value)  	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;  	if (socket[sock].flags & IS_ALIVE) { -		debug(3, "m32r_cfc: pcc_get_status: sock(%d) -EINVAL\n", sock); +		dev_dbg(&s->dev, "pcc_get_status: sock(%d) -EINVAL\n", sock);  		*value = 0;  		return -EINVAL;  	} -	debug(3, "m32r_cfc: pcc_get_status: sock(%d)\n", sock); +	dev_dbg(&s->dev, "pcc_get_status: sock(%d)\n", sock);  	LOCKED(_pcc_get_status(sock, value));  } @@ -653,10 +640,10 @@ static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)  	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;  	if (socket[sock].flags & IS_ALIVE) { -		debug(3, "m32r_cfc: pcc_set_socket: sock(%d) -EINVAL\n", sock); +		dev_dbg(&s->dev, "pcc_set_socket: sock(%d) -EINVAL\n", sock);  		return -EINVAL;  	} -	debug(3, "m32r_cfc: pcc_set_socket: sock(%d)\n", sock); +	dev_dbg(&s->dev, "pcc_set_socket: sock(%d)\n", sock);  	LOCKED(_pcc_set_socket(sock, state));  } @@ -665,10 +652,10 @@ static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)  	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;  	if (socket[sock].flags & IS_ALIVE) { -		debug(3, "m32r_cfc: pcc_set_io_map: sock(%d) -EINVAL\n", sock); +		dev_dbg(&s->dev, "pcc_set_io_map: sock(%d) -EINVAL\n", sock);  		return -EINVAL;  	} -	debug(3, "m32r_cfc: pcc_set_io_map: sock(%d)\n", sock); +	dev_dbg(&s->dev, "pcc_set_io_map: sock(%d)\n", sock);  	LOCKED(_pcc_set_io_map(sock, io));  } @@ -677,16 +664,16 @@ static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)  	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;  	if (socket[sock].flags & IS_ALIVE) { -		debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d) -EINVAL\n", sock); +		dev_dbg(&s->dev, "pcc_set_mem_map: sock(%d) -EINVAL\n", sock);  		return -EINVAL;  	} -	debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d)\n", sock); +	dev_dbg(&s->dev, "pcc_set_mem_map: sock(%d)\n", sock);  	LOCKED(_pcc_set_mem_map(sock, mem));  }  static int pcc_init(struct pcmcia_socket *s)  { -	debug(3, "m32r_cfc: pcc_init()\n"); +	dev_dbg(&s->dev, "pcc_init()\n");  	return 0;  } diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index c6524f99ccc..72844c5a6d0 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -45,16 +45,6 @@  #define PCC_DEBUG_DBEX -#ifdef CONFIG_PCMCIA_DEBUG -static int m32r_pcc_debug; -module_param(m32r_pcc_debug, int, 0644); -#define debug(lvl, fmt, arg...) do {				\ -	if (m32r_pcc_debug > (lvl))				\ -		printk(KERN_DEBUG "m32r_pcc: " fmt , ## arg);	\ -} while (0) -#else -#define debug(n, args...) do { } while (0) -#endif  /* Poll status interval -- 0 means default to interrupt */  static int poll_interval = 0; @@ -358,7 +348,7 @@ static irqreturn_t pcc_interrupt(int irq, void *dev)  	u_int events, active;  	int handled = 0; -	debug(4, "m32r: pcc_interrupt(%d)\n", irq); +	pr_debug("m32r_pcc: pcc_interrupt(%d)\n", irq);  	for (j = 0; j < 20; j++) {  		active = 0; @@ -369,13 +359,14 @@ static irqreturn_t pcc_interrupt(int irq, void *dev)  			handled = 1;  			irc = pcc_get(i, PCIRC);  			irc >>=16; -			debug(2, "m32r-pcc:interrupt: socket %d pcirc 0x%02x ", i, irc); +			pr_debug("m32r_pcc: interrupt: socket %d pcirc 0x%02x ", +				i, irc);  			if (!irc)  				continue;  			events = (irc) ? SS_DETECT : 0;  			events |= (pcc_get(i,PCCR) & PCCR_PCEN) ? SS_READY : 0; -			debug(2, " event 0x%02x\n", events); +			pr_debug("m32r_pcc: event 0x%02x\n", events);  			if (events)  				pcmcia_parse_events(&socket[i].socket, events); @@ -388,7 +379,7 @@ static irqreturn_t pcc_interrupt(int irq, void *dev)  	if (j == 20)  		printk(KERN_NOTICE "m32r-pcc: infinite loop in interrupt handler\n"); -	debug(4, "m32r-pcc: interrupt done\n"); +	pr_debug("m32r_pcc: interrupt done\n");  	return IRQ_RETVAL(handled);  } /* pcc_interrupt */ @@ -422,7 +413,7 @@ static int _pcc_get_status(u_short sock, u_int *value)  	status = pcc_get(sock,PCCSIGCR);  	*value |= (status & PCCSIGCR_VEN) ? SS_POWERON : 0; -	debug(3, "m32r-pcc: GetStatus(%d) = %#4.4x\n", sock, *value); +	pr_debug("m32r_pcc: GetStatus(%d) = %#4.4x\n", sock, *value);  	return 0;  } /* _get_status */ @@ -432,7 +423,7 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)  {  	u_long reg = 0; -	debug(3, "m32r-pcc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " +	pr_debug("m32r_pcc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "  		  "io_irq %d, csc_mask %#2.2x)", sock, state->flags,  		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask); @@ -448,11 +439,11 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)  	}  	if (state->flags & SS_RESET) { -		debug(3, ":RESET\n"); +		pr_debug("m32r_pcc: :RESET\n");  		reg |= PCCSIGCR_CRST;  	}  	if (state->flags & SS_OUTPUT_ENA){ -		debug(3, ":OUTPUT_ENA\n"); +		pr_debug("m32r_pcc: :OUTPUT_ENA\n");  		/* bit clear */  	} else {  		reg |= PCCSIGCR_SEN; @@ -460,28 +451,26 @@ static int _pcc_set_socket(u_short sock, socket_state_t *state)  	pcc_set(sock,PCCSIGCR,reg); -#ifdef CONFIG_PCMCIA_DEBUG  	if(state->flags & SS_IOCARD){ -		debug(3, ":IOCARD"); +		pr_debug("m32r_pcc: :IOCARD");  	}  	if (state->flags & SS_PWR_AUTO) { -		debug(3, ":PWR_AUTO"); +		pr_debug("m32r_pcc: :PWR_AUTO");  	}  	if (state->csc_mask & SS_DETECT) -		debug(3, ":csc-SS_DETECT"); +		pr_debug("m32r_pcc: :csc-SS_DETECT");  	if (state->flags & SS_IOCARD) {  		if (state->csc_mask & SS_STSCHG) -			debug(3, ":STSCHG"); +			pr_debug("m32r_pcc: :STSCHG");  	} else {  		if (state->csc_mask & SS_BATDEAD) -			debug(3, ":BATDEAD"); +			pr_debug("m32r_pcc: :BATDEAD");  		if (state->csc_mask & SS_BATWARN) -			debug(3, ":BATWARN"); +			pr_debug("m32r_pcc: :BATWARN");  		if (state->csc_mask & SS_READY) -			debug(3, ":READY"); +			pr_debug("m32r_pcc: :READY");  	} -	debug(3, "\n"); -#endif +	pr_debug("m32r_pcc: \n");  	return 0;  } /* _set_socket */ @@ -491,7 +480,7 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)  {  	u_char map; -	debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m32r_pcc: SetIOMap(%d, %d, %#2.2x, %d ns, "  		  "%#llx-%#llx)\n", sock, io->map, io->flags,  		  io->speed, (unsigned long long)io->start,  		  (unsigned long long)io->stop); @@ -515,7 +504,7 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)  #endif  #endif -	debug(3, "m32r-pcc: SetMemMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m32r_pcc: SetMemMap(%d, %d, %#2.2x, %d ns, "  		 "%#llx,  %#x)\n", sock, map, mem->flags,  		 mem->speed, (unsigned long long)mem->static_start,  		 mem->card_start); @@ -662,7 +651,7 @@ static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)  static int pcc_init(struct pcmcia_socket *s)  { -	debug(4, "m32r-pcc: init call\n"); +	pr_debug("m32r_pcc: init call\n");  	return 0;  } diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 403559ba49d..7f79c4e169a 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c @@ -64,14 +64,6 @@  #include <pcmcia/cs.h>  #include <pcmcia/ss.h> -#ifdef CONFIG_PCMCIA_DEBUG -static int pc_debug; -module_param(pc_debug, int, 0); -#define dprintk(args...) printk(KERN_DEBUG "m8xx_pcmcia: " args); -#else -#define dprintk(args...) -#endif -  #define pcmcia_info(args...) printk(KERN_INFO "m8xx_pcmcia: "args)  #define pcmcia_error(args...) printk(KERN_ERR "m8xx_pcmcia: "args) @@ -565,7 +557,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)  	unsigned int i, events, pscr, pipr, per;  	pcmconf8xx_t *pcmcia = socket[0].pcmcia; -	dprintk("Interrupt!\n"); +	pr_debug("m8xx_pcmcia: Interrupt!\n");  	/* get interrupt sources */  	pscr = in_be32(&pcmcia->pcmc_pscr); @@ -614,7 +606,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)  		/* call the handler */ -		dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, " +		pr_debug("m8xx_pcmcia: slot %u: events = 0x%02x, pscr = 0x%08x, "  			"pipr = 0x%08x\n", i, events, pscr, pipr);  		if (events) { @@ -641,7 +633,7 @@ static irqreturn_t m8xx_interrupt(int irq, void *dev)  	/* clear the interrupt sources */  	out_be32(&pcmcia->pcmc_pscr, pscr); -	dprintk("Interrupt done.\n"); +	pr_debug("m8xx_pcmcia: Interrupt done.\n");  	return IRQ_HANDLED;  } @@ -815,7 +807,7 @@ static int m8xx_get_status(struct pcmcia_socket *sock, unsigned int *value)  		};  	} -	dprintk("GetStatus(%d) = %#2.2x\n", lsock, *value); +	pr_debug("m8xx_pcmcia: GetStatus(%d) = %#2.2x\n", lsock, *value);  	return 0;  } @@ -828,7 +820,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)  	unsigned long flags;  	pcmconf8xx_t *pcmcia = socket[0].pcmcia; -	dprintk("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " +	pr_debug("m8xx_pcmcia: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "  		"io_irq %d, csc_mask %#2.2x)\n", lsock, state->flags,  		state->Vcc, state->Vpp, state->io_irq, state->csc_mask); @@ -974,7 +966,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)  #define M8XX_SIZE (io->stop - io->start + 1)  #define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start) -	dprintk("SetIOMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m8xx_pcmcia: SetIOMap(%d, %d, %#2.2x, %d ns, "  		"%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,  		io->speed, (unsigned long long)io->start,  		(unsigned long long)io->stop); @@ -988,7 +980,7 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)  	if (io->flags & MAP_ACTIVE) { -		dprintk("io->flags & MAP_ACTIVE\n"); +		pr_debug("m8xx_pcmcia: io->flags & MAP_ACTIVE\n");  		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO)  		    + (lsock * PCMCIA_IO_WIN_NO) + io->map; @@ -1018,8 +1010,8 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)  		out_be32(&w->or, reg); -		dprintk("Socket %u: Mapped io window %u at %#8.8x, " -			"OR = %#8.8x.\n", lsock, io->map, w->br, w->or); +		pr_debug("m8xx_pcmcia: Socket %u: Mapped io window %u at " +			"%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);  	} else {  		/* shutdown IO window */  		winnr = (PCMCIA_MEM_WIN_NO * PCMCIA_SOCKETS_NO) @@ -1033,14 +1025,14 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)  		out_be32(&w->or, 0);	/* turn off window */  		out_be32(&w->br, 0);	/* turn off base address */ -		dprintk("Socket %u: Unmapped io window %u at %#8.8x, " -			"OR = %#8.8x.\n", lsock, io->map, w->br, w->or); +		pr_debug("m8xx_pcmcia: Socket %u: Unmapped io window %u at " +			"%#8.8x, OR = %#8.8x.\n", lsock, io->map, w->br, w->or);  	}  	/* copy the struct and modify the copy */  	s->io_win[io->map] = *io;  	s->io_win[io->map].flags &= (MAP_WRPROT | MAP_16BIT | MAP_ACTIVE); -	dprintk("SetIOMap exit\n"); +	pr_debug("m8xx_pcmcia: SetIOMap exit\n");  	return 0;  } @@ -1055,7 +1047,7 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,  	unsigned int reg, winnr;  	pcmconf8xx_t *pcmcia = s->pcmcia; -	dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "  		"%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,  		mem->speed, (unsigned long long)mem->static_start,  		mem->card_start); @@ -1098,7 +1090,7 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,  	out_be32(&w->or, reg); -	dprintk("Socket %u: Mapped memory window %u at %#8.8x, " +	pr_debug("m8xx_pcmcia: Socket %u: Mapped memory window %u at %#8.8x, "  		"OR = %#8.8x.\n", lsock, mem->map, w->br, w->or);  	if (mem->flags & MAP_ACTIVE) { @@ -1108,7 +1100,7 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,  		    + mem->card_start;  	} -	dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, " +	pr_debug("m8xx_pcmcia: SetMemMap(%d, %d, %#2.2x, %d ns, "  		"%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,  		mem->speed, (unsigned long long)mem->static_start,  		mem->card_start); @@ -1129,7 +1121,7 @@ static int m8xx_sock_init(struct pcmcia_socket *sock)  	pccard_io_map io = { 0, 0, 0, 0, 1 };  	pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 }; -	dprintk("sock_init(%d)\n", s); +	pr_debug("m8xx_pcmcia: sock_init(%d)\n", s);  	m8xx_set_socket(sock, &dead_socket);  	for (i = 0; i < PCMCIA_IO_WIN_NO; i++) { diff --git a/drivers/pcmcia/o2micro.h b/drivers/pcmcia/o2micro.h index 72188c462c9..624442fc0d3 100644 --- a/drivers/pcmcia/o2micro.h +++ b/drivers/pcmcia/o2micro.h @@ -30,28 +30,6 @@  #ifndef _LINUX_O2MICRO_H  #define _LINUX_O2MICRO_H -#ifndef PCI_VENDOR_ID_O2 -#define PCI_VENDOR_ID_O2		0x1217 -#endif -#ifndef PCI_DEVICE_ID_O2_6729 -#define PCI_DEVICE_ID_O2_6729		0x6729 -#endif -#ifndef PCI_DEVICE_ID_O2_6730 -#define PCI_DEVICE_ID_O2_6730		0x673a -#endif -#ifndef PCI_DEVICE_ID_O2_6832 -#define PCI_DEVICE_ID_O2_6832		0x6832 -#endif -#ifndef PCI_DEVICE_ID_O2_6836 -#define PCI_DEVICE_ID_O2_6836		0x6836 -#endif -#ifndef PCI_DEVICE_ID_O2_6812 -#define PCI_DEVICE_ID_O2_6812		0x6872 -#endif -#ifndef PCI_DEVICE_ID_O2_6933 -#define PCI_DEVICE_ID_O2_6933           0x6933 -#endif -  /* Additional PCI configuration registers */  #define O2_MUX_CONTROL		0x90	/* 32 bit */ diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 30cf71d2ee2..c4d7908fa37 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c @@ -58,17 +58,6 @@ typedef struct user_info_t {  } user_info_t; -#ifdef CONFIG_PCMCIA_DEBUG -extern int ds_pc_debug; - -#define ds_dbg(lvl, fmt, arg...) do {		\ -	if (ds_pc_debug >= lvl)				\ -		printk(KERN_DEBUG "ds: " fmt , ## arg);		\ -} while (0) -#else -#define ds_dbg(lvl, fmt, arg...) do { } while (0) -#endif -  static struct pcmcia_device *get_pcmcia_device(struct pcmcia_socket *s,  						unsigned int function)  { @@ -229,6 +218,61 @@ static int pcmcia_adjust_resource_info(adjust_t *adj)  	return (ret);  } + +/** pcmcia_get_window + */ +static int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *wh_out, +			window_handle_t wh, win_req_t *req) +{ +	pccard_mem_map *win; +	window_handle_t w; + +	wh--; +	if (!s || !(s->state & SOCKET_PRESENT)) +		return -ENODEV; +	if (wh >= MAX_WIN) +		return -EINVAL; +	for (w = wh; w < MAX_WIN; w++) +		if (s->state & SOCKET_WIN_REQ(w)) +			break; +	if (w == MAX_WIN) +		return -EINVAL; +	win = &s->win[w]; +	req->Base = win->res->start; +	req->Size = win->res->end - win->res->start + 1; +	req->AccessSpeed = win->speed; +	req->Attributes = 0; +	if (win->flags & MAP_ATTRIB) +		req->Attributes |= WIN_MEMORY_TYPE_AM; +	if (win->flags & MAP_ACTIVE) +		req->Attributes |= WIN_ENABLE; +	if (win->flags & MAP_16BIT) +		req->Attributes |= WIN_DATA_WIDTH_16; +	if (win->flags & MAP_USE_WAIT) +		req->Attributes |= WIN_USE_WAIT; + +	*wh_out = w + 1; +	return 0; +} /* pcmcia_get_window */ + + +/** pcmcia_get_mem_page + * + * Change the card address of an already open memory window. + */ +static int pcmcia_get_mem_page(struct pcmcia_socket *skt, window_handle_t wh, +			memreq_t *req) +{ +	wh--; +	if (wh >= MAX_WIN) +		return -EINVAL; + +	req->Page = 0; +	req->CardOffset = skt->win[wh].card_start; +	return 0; +} /* pcmcia_get_mem_page */ + +  /** pccard_get_status   *   * Get the current socket state bits.  We don't support the latched @@ -431,7 +475,7 @@ static int bind_request(struct pcmcia_socket *s, bind_info_t *bind_info)  	if (!s)  		return -EINVAL; -	ds_dbg(2, "bind_request(%d, '%s')\n", s->sock, +	pr_debug("bind_request(%d, '%s')\n", s->sock,  	       (char *)bind_info->dev_info);  	p_drv = get_pcmcia_driver(&bind_info->dev_info); @@ -623,7 +667,7 @@ static int ds_open(struct inode *inode, struct file *file)      static int warning_printed = 0;      int ret = 0; -    ds_dbg(0, "ds_open(socket %d)\n", i); +    pr_debug("ds_open(socket %d)\n", i);      lock_kernel();      s = pcmcia_get_socket_by_nr(i); @@ -685,7 +729,7 @@ static int ds_release(struct inode *inode, struct file *file)      struct pcmcia_socket *s;      user_info_t *user, **link; -    ds_dbg(0, "ds_release(socket %d)\n", iminor(inode)); +    pr_debug("ds_release(socket %d)\n", iminor(inode));      user = file->private_data;      if (CHECK_USER(user)) @@ -719,7 +763,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,      user_info_t *user;      int ret; -    ds_dbg(2, "ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode)); +    pr_debug("ds_read(socket %d)\n", iminor(file->f_path.dentry->d_inode));      if (count < 4)  	return -EINVAL; @@ -744,7 +788,7 @@ static ssize_t ds_read(struct file *file, char __user *buf,  static ssize_t ds_write(struct file *file, const char __user *buf,  			size_t count, loff_t *ppos)  { -    ds_dbg(2, "ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode)); +    pr_debug("ds_write(socket %d)\n", iminor(file->f_path.dentry->d_inode));      if (count != 4)  	return -EINVAL; @@ -762,7 +806,7 @@ static u_int ds_poll(struct file *file, poll_table *wait)      struct pcmcia_socket *s;      user_info_t *user; -    ds_dbg(2, "ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode)); +    pr_debug("ds_poll(socket %d)\n", iminor(file->f_path.dentry->d_inode));      user = file->private_data;      if (CHECK_USER(user)) @@ -790,7 +834,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,      ds_ioctl_arg_t *buf;      user_info_t *user; -    ds_dbg(2, "ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg); +    pr_debug("ds_ioctl(socket %d, %#x, %#lx)\n", iminor(inode), cmd, arg);      user = file->private_data;      if (CHECK_USER(user)) @@ -809,13 +853,13 @@ static int ds_ioctl(struct inode * inode, struct file * file,      if (cmd & IOC_IN) {  	if (!access_ok(VERIFY_READ, uarg, size)) { -	    ds_dbg(3, "ds_ioctl(): verify_read = %d\n", -EFAULT); +	    pr_debug("ds_ioctl(): verify_read = %d\n", -EFAULT);  	    return -EFAULT;  	}      }      if (cmd & IOC_OUT) {  	if (!access_ok(VERIFY_WRITE, uarg, size)) { -	    ds_dbg(3, "ds_ioctl(): verify_write = %d\n", -EFAULT); +	    pr_debug("ds_ioctl(): verify_write = %d\n", -EFAULT);  	    return -EFAULT;  	}      } @@ -927,15 +971,15 @@ static int ds_ioctl(struct inode * inode, struct file * file,  	goto free_out;  	break;      case DS_GET_FIRST_WINDOW: -	ret = pcmcia_get_window(s, &buf->win_info.handle, 0, +	ret = pcmcia_get_window(s, &buf->win_info.handle, 1,  			&buf->win_info.window);  	break;      case DS_GET_NEXT_WINDOW:  	ret = pcmcia_get_window(s, &buf->win_info.handle, -			buf->win_info.handle->index + 1, &buf->win_info.window); +			buf->win_info.handle + 1, &buf->win_info.window);  	break;      case DS_GET_MEM_PAGE: -	ret = pcmcia_get_mem_page(buf->win_info.handle, +	ret = pcmcia_get_mem_page(s, buf->win_info.handle,  			   &buf->win_info.map);  	break;      case DS_REPLACE_CIS: @@ -962,7 +1006,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,      }      if ((err == 0) && (ret != 0)) { -	ds_dbg(2, "ds_ioctl: ret = %d\n", ret); +	pr_debug("ds_ioctl: ret = %d\n", ret);  	switch (ret) {  	case -ENODEV:  	case -EINVAL: diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c index d919e96c0af..a8bf8c1b45e 100644 --- a/drivers/pcmcia/pcmcia_resource.c +++ b/drivers/pcmcia/pcmcia_resource.c @@ -20,6 +20,7 @@  #include <linux/delay.h>  #include <linux/pci.h>  #include <linux/device.h> +#include <linux/netdevice.h>  #include <pcmcia/cs_types.h>  #include <pcmcia/ss.h> @@ -43,21 +44,6 @@ static u8 pcmcia_used_irq[NR_IRQS];  #endif -#ifdef CONFIG_PCMCIA_DEBUG -extern int ds_pc_debug; - -#define ds_dbg(skt, lvl, fmt, arg...) do {			\ -	if (ds_pc_debug >= lvl)					\ -		dev_printk(KERN_DEBUG, &skt->dev,		\ -			   "pcmcia_resource: " fmt,		\ -			   ## arg);				\ -} while (0) -#else -#define ds_dbg(skt, lvl, fmt, arg...) do { } while (0) -#endif - - -  /** alloc_io_space   *   * Special stuff for managing IO windows, because they are scarce @@ -72,14 +58,14 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr,  	align = (*base) ? (lines ? 1<<lines : 0) : 1;  	if (align && (align < num)) {  		if (*base) { -			ds_dbg(s, 0, "odd IO request: num %#x align %#x\n", +			dev_dbg(&s->dev, "odd IO request: num %#x align %#x\n",  			       num, align);  			align = 0;  		} else  			while (align && (align < num)) align <<= 1;  	}  	if (*base & ~(align-1)) { -		ds_dbg(s, 0, "odd IO request: base %#x align %#x\n", +		dev_dbg(&s->dev, "odd IO request: base %#x align %#x\n",  		       *base, align);  		align = 0;  	} @@ -173,8 +159,10 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,  	s = p_dev->socket;  	c = p_dev->function_config; -	if (!(c->state & CONFIG_LOCKED)) +	if (!(c->state & CONFIG_LOCKED)) { +		dev_dbg(&s->dev, "Configuration isnt't locked\n");  		return -EACCES; +	}  	addr = (c->ConfigBase + reg->Offset) >> 1; @@ -188,6 +176,7 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,  		pcmcia_write_cis_mem(s, 1, addr, 1, &val);  		break;  	default: +		dev_dbg(&s->dev, "Invalid conf register request\n");  		return -EINVAL;  		break;  	} @@ -196,68 +185,21 @@ int pcmcia_access_configuration_register(struct pcmcia_device *p_dev,  EXPORT_SYMBOL(pcmcia_access_configuration_register); -/** pcmcia_get_window - */ -int pcmcia_get_window(struct pcmcia_socket *s, window_handle_t *handle, -		      int idx, win_req_t *req) -{ -	window_t *win; -	int w; - -	if (!s || !(s->state & SOCKET_PRESENT)) -		return -ENODEV; -	for (w = idx; w < MAX_WIN; w++) -		if (s->state & SOCKET_WIN_REQ(w)) -			break; -	if (w == MAX_WIN) -		return -EINVAL; -	win = &s->win[w]; -	req->Base = win->ctl.res->start; -	req->Size = win->ctl.res->end - win->ctl.res->start + 1; -	req->AccessSpeed = win->ctl.speed; -	req->Attributes = 0; -	if (win->ctl.flags & MAP_ATTRIB) -		req->Attributes |= WIN_MEMORY_TYPE_AM; -	if (win->ctl.flags & MAP_ACTIVE) -		req->Attributes |= WIN_ENABLE; -	if (win->ctl.flags & MAP_16BIT) -		req->Attributes |= WIN_DATA_WIDTH_16; -	if (win->ctl.flags & MAP_USE_WAIT) -		req->Attributes |= WIN_USE_WAIT; -	*handle = win; -	return 0; -} /* pcmcia_get_window */ -EXPORT_SYMBOL(pcmcia_get_window); - - -/** pcmcia_get_mem_page - * - * Change the card address of an already open memory window. - */ -int pcmcia_get_mem_page(window_handle_t win, memreq_t *req) +int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t wh, +			memreq_t *req)  { -	if ((win == NULL) || (win->magic != WINDOW_MAGIC)) -		return -EINVAL; -	req->Page = 0; -	req->CardOffset = win->ctl.card_start; -	return 0; -} /* pcmcia_get_mem_page */ -EXPORT_SYMBOL(pcmcia_get_mem_page); - +	struct pcmcia_socket *s = p_dev->socket; -int pcmcia_map_mem_page(window_handle_t win, memreq_t *req) -{ -	struct pcmcia_socket *s; -	if ((win == NULL) || (win->magic != WINDOW_MAGIC)) +	wh--; +	if (wh >= MAX_WIN)  		return -EINVAL; -	s = win->sock;  	if (req->Page != 0) { -		ds_dbg(s, 0, "failure: requested page is zero\n"); +		dev_dbg(&s->dev, "failure: requested page is zero\n");  		return -EINVAL;  	} -	win->ctl.card_start = req->CardOffset; -	if (s->ops->set_mem_map(s, &win->ctl) != 0) { -		ds_dbg(s, 0, "failed to set_mem_map\n"); +	s->win[wh].card_start = req->CardOffset; +	if (s->ops->set_mem_map(s, &s->win[wh]) != 0) { +		dev_dbg(&s->dev, "failed to set_mem_map\n");  		return -EIO;  	}  	return 0; @@ -278,10 +220,14 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,  	s = p_dev->socket;  	c = p_dev->function_config; -	if (!(s->state & SOCKET_PRESENT)) +	if (!(s->state & SOCKET_PRESENT)) { +		dev_dbg(&s->dev, "No card present\n");  		return -ENODEV; -	if (!(c->state & CONFIG_LOCKED)) +	} +	if (!(c->state & CONFIG_LOCKED)) { +		dev_dbg(&s->dev, "Configuration isnt't locked\n");  		return -EACCES; +	}  	if (mod->Attributes & CONF_IRQ_CHANGE_VALID) {  		if (mod->Attributes & CONF_ENABLE_IRQ) { @@ -295,7 +241,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,  	}  	if (mod->Attributes & CONF_VCC_CHANGE_VALID) { -		ds_dbg(s, 0, "changing Vcc is not allowed at this time\n"); +		dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");  		return -EINVAL;  	} @@ -303,7 +249,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,  	if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) &&  	    (mod->Attributes & CONF_VPP2_CHANGE_VALID)) {  		if (mod->Vpp1 != mod->Vpp2) { -			ds_dbg(s, 0, "Vpp1 and Vpp2 must be the same\n"); +			dev_dbg(&s->dev, "Vpp1 and Vpp2 must be the same\n");  			return -EINVAL;  		}  		s->socket.Vpp = mod->Vpp1; @@ -314,7 +260,7 @@ int pcmcia_modify_configuration(struct pcmcia_device *p_dev,  		}  	} else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) ||  		   (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { -		ds_dbg(s, 0, "changing Vcc is not allowed at this time\n"); +		dev_dbg(&s->dev, "changing Vcc is not allowed at this time\n");  		return -EINVAL;  	} @@ -425,11 +371,11 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)  	if (c->state & CONFIG_LOCKED)  		return -EACCES;  	if (c->irq.Attributes != req->Attributes) { -		ds_dbg(s, 0, "IRQ attributes must match assigned ones\n"); +		dev_dbg(&s->dev, "IRQ attributes must match assigned ones\n");  		return -EINVAL;  	}  	if (s->irq.AssignedIRQ != req->AssignedIRQ) { -		ds_dbg(s, 0, "IRQ must match assigned one\n"); +		dev_dbg(&s->dev, "IRQ must match assigned one\n");  		return -EINVAL;  	}  	if (--s->irq.Config == 0) { @@ -437,8 +383,8 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)  		s->irq.AssignedIRQ = 0;  	} -	if (req->Attributes & IRQ_HANDLE_PRESENT) { -		free_irq(req->AssignedIRQ, req->Instance); +	if (req->Handler) { +		free_irq(req->AssignedIRQ, p_dev->priv);  	}  #ifdef CONFIG_PCMCIA_PROBE @@ -449,30 +395,34 @@ static int pcmcia_release_irq(struct pcmcia_device *p_dev, irq_req_t *req)  } /* pcmcia_release_irq */ -int pcmcia_release_window(window_handle_t win) +int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t wh)  { -	struct pcmcia_socket *s; +	struct pcmcia_socket *s = p_dev->socket; +	pccard_mem_map *win; -	if ((win == NULL) || (win->magic != WINDOW_MAGIC)) +	wh--; +	if (wh >= MAX_WIN)  		return -EINVAL; -	s = win->sock; -	if (!(win->handle->_win & CLIENT_WIN_REQ(win->index))) + +	win = &s->win[wh]; + +	if (!(p_dev->_win & CLIENT_WIN_REQ(wh))) { +		dev_dbg(&s->dev, "not releasing unknown window\n");  		return -EINVAL; +	}  	/* Shut down memory window */ -	win->ctl.flags &= ~MAP_ACTIVE; -	s->ops->set_mem_map(s, &win->ctl); -	s->state &= ~SOCKET_WIN_REQ(win->index); +	win->flags &= ~MAP_ACTIVE; +	s->ops->set_mem_map(s, win); +	s->state &= ~SOCKET_WIN_REQ(wh);  	/* Release system memory */ -	if (win->ctl.res) { -		release_resource(win->ctl.res); -		kfree(win->ctl.res); -		win->ctl.res = NULL; +	if (win->res) { +		release_resource(win->res); +		kfree(win->res); +		win->res = NULL;  	} -	win->handle->_win &= ~CLIENT_WIN_REQ(win->index); - -	win->magic = 0; +	p_dev->_win &= ~CLIENT_WIN_REQ(wh);  	return 0;  } /* pcmcia_release_window */ @@ -492,12 +442,14 @@ int pcmcia_request_configuration(struct pcmcia_device *p_dev,  		return -ENODEV;  	if (req->IntType & INT_CARDBUS) { -		ds_dbg(p_dev->socket, 0, "IntType may not be INT_CARDBUS\n"); +		dev_dbg(&s->dev, "IntType may not be INT_CARDBUS\n");  		return -EINVAL;  	}  	c = p_dev->function_config; -	if (c->state & CONFIG_LOCKED) +	if (c->state & CONFIG_LOCKED) { +		dev_dbg(&s->dev, "Configuration is locked\n");  		return -EACCES; +	}  	/* Do power control.  We don't allow changes in Vcc. */  	s->socket.Vpp = req->Vpp; @@ -609,40 +561,44 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req)  	struct pcmcia_socket *s = p_dev->socket;  	config_t *c; -	if (!(s->state & SOCKET_PRESENT)) +	if (!(s->state & SOCKET_PRESENT)) { +		dev_dbg(&s->dev, "No card present\n");  		return -ENODEV; +	}  	if (!req)  		return -EINVAL;  	c = p_dev->function_config; -	if (c->state & CONFIG_LOCKED) +	if (c->state & CONFIG_LOCKED) { +		dev_dbg(&s->dev, "Configuration is locked\n");  		return -EACCES; +	}  	if (c->state & CONFIG_IO_REQ) { -		ds_dbg(s, 0, "IO already configured\n"); +		dev_dbg(&s->dev, "IO already configured\n");  		return -EBUSY;  	}  	if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) { -		ds_dbg(s, 0, "bad attribute setting for IO region 1\n"); +		dev_dbg(&s->dev, "bad attribute setting for IO region 1\n");  		return -EINVAL;  	}  	if ((req->NumPorts2 > 0) &&  	    (req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) { -		ds_dbg(s, 0, "bad attribute setting for IO region 2\n"); +		dev_dbg(&s->dev, "bad attribute setting for IO region 2\n");  		return -EINVAL;  	} -	ds_dbg(s, 1, "trying to allocate resource 1\n"); +	dev_dbg(&s->dev, "trying to allocate resource 1\n");  	if (alloc_io_space(s, req->Attributes1, &req->BasePort1,  			   req->NumPorts1, req->IOAddrLines)) { -		ds_dbg(s, 0, "allocation of resource 1 failed\n"); +		dev_dbg(&s->dev, "allocation of resource 1 failed\n");  		return -EBUSY;  	}  	if (req->NumPorts2) { -		ds_dbg(s, 1, "trying to allocate resource 2\n"); +		dev_dbg(&s->dev, "trying to allocate resource 2\n");  		if (alloc_io_space(s, req->Attributes2, &req->BasePort2,  				   req->NumPorts2, req->IOAddrLines)) { -			ds_dbg(s, 0, "allocation of resource 2 failed\n"); +			dev_dbg(&s->dev, "allocation of resource 2 failed\n");  			release_io_space(s, req->BasePort1, req->NumPorts1);  			return -EBUSY;  		} @@ -680,13 +636,17 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)  	int ret = -EINVAL, irq = 0;  	int type; -	if (!(s->state & SOCKET_PRESENT)) +	if (!(s->state & SOCKET_PRESENT)) { +		dev_dbg(&s->dev, "No card present\n");  		return -ENODEV; +	}  	c = p_dev->function_config; -	if (c->state & CONFIG_LOCKED) +	if (c->state & CONFIG_LOCKED) { +		dev_dbg(&s->dev, "Configuration is locked\n");  		return -EACCES; +	}  	if (c->state & CONFIG_IRQ_REQ) { -		ds_dbg(s, 0, "IRQ already configured\n"); +		dev_dbg(&s->dev, "IRQ already configured\n");  		return -EBUSY;  	} @@ -704,7 +664,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)  	/* if the underlying IRQ infrastructure allows for it, only allocate  	 * the IRQ, but do not enable it  	 */ -	if (!(req->Attributes & IRQ_HANDLE_PRESENT)) +	if (!(req->Handler))  		type |= IRQ_NOAUTOEN;  #endif /* IRQ_NOAUTOEN */ @@ -714,7 +674,7 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)  	} else {  		int try;  		u32 mask = s->irq_mask; -		void *data = &p_dev->dev.driver; /* something unique to this device */ +		void *data = p_dev; /* something unique to this device */  		for (try = 0; try < 64; try++) {  			irq = try % 32; @@ -731,12 +691,12 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)  			 * registering a dummy handle works, i.e. if the IRQ isn't  			 * marked as used by the kernel resource management core */  			ret = request_irq(irq, -					  (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Handler : test_action, +					  (req->Handler) ? req->Handler : test_action,  					  type,  					  p_dev->devname, -					  (req->Attributes & IRQ_HANDLE_PRESENT) ? req->Instance : data); +					  (req->Handler) ? p_dev->priv : data);  			if (!ret) { -				if (!(req->Attributes & IRQ_HANDLE_PRESENT)) +				if (!req->Handler)  					free_irq(irq, data);  				break;  			} @@ -745,17 +705,22 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req)  #endif  	/* only assign PCI irq if no IRQ already assigned */  	if (ret && !s->irq.AssignedIRQ) { -		if (!s->pci_irq) +		if (!s->pci_irq) { +			dev_printk(KERN_INFO, &s->dev, "no IRQ found\n");  			return ret; +		}  		type = IRQF_SHARED;  		irq = s->pci_irq;  	} -	if (ret && (req->Attributes & IRQ_HANDLE_PRESENT)) { +	if (ret && req->Handler) {  		ret = request_irq(irq, req->Handler, type, -				  p_dev->devname, req->Instance); -		if (ret) +				  p_dev->devname, p_dev->priv); +		if (ret) { +			dev_printk(KERN_INFO, &s->dev, +				"request_irq() failed\n");  			return ret; +		}  	}  	/* Make sure the fact the request type was overridden is passed back */ @@ -787,17 +752,19 @@ EXPORT_SYMBOL(pcmcia_request_irq);   * Request_window() establishes a mapping between card memory space   * and system memory space.   */ -int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh) +int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req, window_handle_t *wh)  { -	struct pcmcia_socket *s = (*p_dev)->socket; -	window_t *win; +	struct pcmcia_socket *s = p_dev->socket; +	pccard_mem_map *win;  	u_long align;  	int w; -	if (!(s->state & SOCKET_PRESENT)) +	if (!(s->state & SOCKET_PRESENT)) { +		dev_dbg(&s->dev, "No card present\n");  		return -ENODEV; +	}  	if (req->Attributes & (WIN_PAGED | WIN_SHARED)) { -		ds_dbg(s, 0, "bad attribute setting for iomem region\n"); +		dev_dbg(&s->dev, "bad attribute setting for iomem region\n");  		return -EINVAL;  	} @@ -808,12 +775,12 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h  		  (req->Attributes & WIN_STRICT_ALIGN)) ?  		 req->Size : s->map_size);  	if (req->Size & (s->map_size-1)) { -		ds_dbg(s, 0, "invalid map size\n"); +		dev_dbg(&s->dev, "invalid map size\n");  		return -EINVAL;  	}  	if ((req->Base && (s->features & SS_CAP_STATIC_MAP)) ||  	    (req->Base & (align-1))) { -		ds_dbg(s, 0, "invalid base address\n"); +		dev_dbg(&s->dev, "invalid base address\n");  		return -EINVAL;  	}  	if (req->Base) @@ -823,52 +790,48 @@ int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_h  	for (w = 0; w < MAX_WIN; w++)  		if (!(s->state & SOCKET_WIN_REQ(w))) break;  	if (w == MAX_WIN) { -		ds_dbg(s, 0, "all windows are used already\n"); +		dev_dbg(&s->dev, "all windows are used already\n");  		return -EINVAL;  	}  	win = &s->win[w]; -	win->magic = WINDOW_MAGIC; -	win->index = w; -	win->handle = *p_dev; -	win->sock = s;  	if (!(s->features & SS_CAP_STATIC_MAP)) { -		win->ctl.res = pcmcia_find_mem_region(req->Base, req->Size, align, +		win->res = pcmcia_find_mem_region(req->Base, req->Size, align,  						      (req->Attributes & WIN_MAP_BELOW_1MB), s); -		if (!win->ctl.res) { -			ds_dbg(s, 0, "allocating mem region failed\n"); +		if (!win->res) { +			dev_dbg(&s->dev, "allocating mem region failed\n");  			return -EINVAL;  		}  	} -	(*p_dev)->_win |= CLIENT_WIN_REQ(w); +	p_dev->_win |= CLIENT_WIN_REQ(w);  	/* Configure the socket controller */ -	win->ctl.map = w+1; -	win->ctl.flags = 0; -	win->ctl.speed = req->AccessSpeed; +	win->map = w+1; +	win->flags = 0; +	win->speed = req->AccessSpeed;  	if (req->Attributes & WIN_MEMORY_TYPE) -		win->ctl.flags |= MAP_ATTRIB; +		win->flags |= MAP_ATTRIB;  	if (req->Attributes & WIN_ENABLE) -		win->ctl.flags |= MAP_ACTIVE; +		win->flags |= MAP_ACTIVE;  	if (req->Attributes & WIN_DATA_WIDTH_16) -		win->ctl.flags |= MAP_16BIT; +		win->flags |= MAP_16BIT;  	if (req->Attributes & WIN_USE_WAIT) -		win->ctl.flags |= MAP_USE_WAIT; -	win->ctl.card_start = 0; -	if (s->ops->set_mem_map(s, &win->ctl) != 0) { -		ds_dbg(s, 0, "failed to set memory mapping\n"); +		win->flags |= MAP_USE_WAIT; +	win->card_start = 0; +	if (s->ops->set_mem_map(s, win) != 0) { +		dev_dbg(&s->dev, "failed to set memory mapping\n");  		return -EIO;  	}  	s->state |= SOCKET_WIN_REQ(w);  	/* Return window handle */  	if (s->features & SS_CAP_STATIC_MAP) { -		req->Base = win->ctl.static_start; +		req->Base = win->static_start;  	} else { -		req->Base = win->ctl.res->start; +		req->Base = win->res->start;  	} -	*wh = win; +	*wh = w + 1;  	return 0;  } /* pcmcia_request_window */ @@ -879,19 +842,46 @@ void pcmcia_disable_device(struct pcmcia_device *p_dev) {  	pcmcia_release_io(p_dev, &p_dev->io);  	pcmcia_release_irq(p_dev, &p_dev->irq);  	if (p_dev->win) -		pcmcia_release_window(p_dev->win); +		pcmcia_release_window(p_dev, p_dev->win);  }  EXPORT_SYMBOL(pcmcia_disable_device);  struct pcmcia_cfg_mem { -	tuple_t tuple; +	struct pcmcia_device *p_dev; +	void *priv_data; +	int (*conf_check) (struct pcmcia_device *p_dev, +			   cistpl_cftable_entry_t *cfg, +			   cistpl_cftable_entry_t *dflt, +			   unsigned int vcc, +			   void *priv_data);  	cisparse_t parse; -	u8 buf[256];  	cistpl_cftable_entry_t dflt;  };  /** + * pcmcia_do_loop_config() - internal helper for pcmcia_loop_config() + * + * pcmcia_do_loop_config() is the internal callback for the call from + * pcmcia_loop_config() to pccard_loop_tuple(). Data is transferred + * by a struct pcmcia_cfg_mem. + */ +static int pcmcia_do_loop_config(tuple_t *tuple, cisparse_t *parse, void *priv) +{ +	cistpl_cftable_entry_t *cfg = &parse->cftable_entry; +	struct pcmcia_cfg_mem *cfg_mem = priv; + +	/* default values */ +	cfg_mem->p_dev->conf.ConfigIndex = cfg->index; +	if (cfg->flags & CISTPL_CFTABLE_DEFAULT) +		cfg_mem->dflt = *cfg; + +	return cfg_mem->conf_check(cfg_mem->p_dev, cfg, &cfg_mem->dflt, +				   cfg_mem->p_dev->socket->socket.Vcc, +				   cfg_mem->priv_data); +} + +/**   * pcmcia_loop_config() - loop over configuration options   * @p_dev:	the struct pcmcia_device which we need to loop for.   * @conf_check:	function to call for each configuration option. @@ -913,48 +903,174 @@ int pcmcia_loop_config(struct pcmcia_device *p_dev,  		       void *priv_data)  {  	struct pcmcia_cfg_mem *cfg_mem; - -	tuple_t *tuple;  	int ret; -	unsigned int vcc;  	cfg_mem = kzalloc(sizeof(struct pcmcia_cfg_mem), GFP_KERNEL);  	if (cfg_mem == NULL)  		return -ENOMEM; -	/* get the current Vcc setting */ -	vcc = p_dev->socket->socket.Vcc; +	cfg_mem->p_dev = p_dev; +	cfg_mem->conf_check = conf_check; +	cfg_mem->priv_data = priv_data; -	tuple = &cfg_mem->tuple; -	tuple->TupleData = cfg_mem->buf; -	tuple->TupleDataMax = 255; -	tuple->TupleOffset = 0; -	tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; -	tuple->Attributes = 0; +	ret = pccard_loop_tuple(p_dev->socket, p_dev->func, +				CISTPL_CFTABLE_ENTRY, &cfg_mem->parse, +				cfg_mem, pcmcia_do_loop_config); -	ret = pcmcia_get_first_tuple(p_dev, tuple); -	while (!ret) { -		cistpl_cftable_entry_t *cfg = &cfg_mem->parse.cftable_entry; +	kfree(cfg_mem); +	return ret; +} +EXPORT_SYMBOL(pcmcia_loop_config); + + +struct pcmcia_loop_mem { +	struct pcmcia_device *p_dev; +	void *priv_data; +	int (*loop_tuple) (struct pcmcia_device *p_dev, +			   tuple_t *tuple, +			   void *priv_data); +}; + +/** + * pcmcia_do_loop_tuple() - internal helper for pcmcia_loop_config() + * + * pcmcia_do_loop_tuple() is the internal callback for the call from + * pcmcia_loop_tuple() to pccard_loop_tuple(). Data is transferred + * by a struct pcmcia_cfg_mem. + */ +static int pcmcia_do_loop_tuple(tuple_t *tuple, cisparse_t *parse, void *priv) +{ +	struct pcmcia_loop_mem *loop = priv; + +	return loop->loop_tuple(loop->p_dev, tuple, loop->priv_data); +}; + +/** + * pcmcia_loop_tuple() - loop over tuples in the CIS + * @p_dev:	the struct pcmcia_device which we need to loop for. + * @code:	which CIS code shall we look for? + * @priv_data:	private data to be passed to the loop_tuple function. + * @loop_tuple:	function to call for each CIS entry of type @function. IT + *		gets passed the raw tuple and @priv_data. + * + * pcmcia_loop_tuple() loops over all CIS entries of type @function, and + * calls the @loop_tuple function for each entry. If the call to @loop_tuple + * returns 0, the loop exits. Returns 0 on success or errorcode otherwise. + */ +int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, +		      int (*loop_tuple) (struct pcmcia_device *p_dev, +					 tuple_t *tuple, +					 void *priv_data), +		      void *priv_data) +{ +	struct pcmcia_loop_mem loop = { +		.p_dev = p_dev, +		.loop_tuple = loop_tuple, +		.priv_data = priv_data}; + +	return pccard_loop_tuple(p_dev->socket, p_dev->func, code, NULL, +				 &loop, pcmcia_do_loop_tuple); +}; +EXPORT_SYMBOL(pcmcia_loop_tuple); + + +struct pcmcia_loop_get { +	size_t len; +	cisdata_t **buf; +}; + +/** + * pcmcia_do_get_tuple() - internal helper for pcmcia_get_tuple() + * + * pcmcia_do_get_tuple() is the internal callback for the call from + * pcmcia_get_tuple() to pcmcia_loop_tuple(). As we're only interested in + * the first tuple, return 0 unconditionally. Create a memory buffer large + * enough to hold the content of the tuple, and fill it with the tuple data. + * The caller is responsible to free the buffer. + */ +static int pcmcia_do_get_tuple(struct pcmcia_device *p_dev, tuple_t *tuple, +			       void *priv) +{ +	struct pcmcia_loop_get *get = priv; + +	*get->buf = kzalloc(tuple->TupleDataLen, GFP_KERNEL); +	if (*get->buf) { +		get->len = tuple->TupleDataLen; +		memcpy(*get->buf, tuple->TupleData, tuple->TupleDataLen); +	} else +		dev_dbg(&p_dev->dev, "do_get_tuple: out of memory\n"); +	return 0; +}; -		if (pcmcia_get_tuple_data(p_dev, tuple)) -			goto next_entry; +/** + * pcmcia_get_tuple() - get first tuple from CIS + * @p_dev:	the struct pcmcia_device which we need to loop for. + * @code:	which CIS code shall we look for? + * @buf:        pointer to store the buffer to. + * + * pcmcia_get_tuple() gets the content of the first CIS entry of type @code. + * It returns the buffer length (or zero). The caller is responsible to free + * the buffer passed in @buf. + */ +size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, +			unsigned char **buf) +{ +	struct pcmcia_loop_get get = { +		.len = 0, +		.buf = buf, +	}; -		if (pcmcia_parse_tuple(tuple, &cfg_mem->parse)) -			goto next_entry; +	*get.buf = NULL; +	pcmcia_loop_tuple(p_dev, code, pcmcia_do_get_tuple, &get); -		/* default values */ -		p_dev->conf.ConfigIndex = cfg->index; -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			cfg_mem->dflt = *cfg; +	return get.len; +}; +EXPORT_SYMBOL(pcmcia_get_tuple); + + +/** + * pcmcia_do_get_mac() - internal helper for pcmcia_get_mac_from_cis() + * + * pcmcia_do_get_mac() is the internal callback for the call from + * pcmcia_get_mac_from_cis() to pcmcia_loop_tuple(). We check whether the + * tuple contains a proper LAN_NODE_ID of length 6, and copy the data + * to struct net_device->dev_addr[i]. + */ +static int pcmcia_do_get_mac(struct pcmcia_device *p_dev, tuple_t *tuple, +			     void *priv) +{ +	struct net_device *dev = priv; +	int i; -		ret = conf_check(p_dev, cfg, &cfg_mem->dflt, vcc, priv_data); -		if (!ret) -			break; +	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) +		return -EINVAL; +	if (tuple->TupleDataLen < ETH_ALEN + 2) { +		dev_warn(&p_dev->dev, "Invalid CIS tuple length for " +			"LAN_NODE_ID\n"); +		return -EINVAL; +	} -next_entry: -		ret = pcmcia_get_next_tuple(p_dev, tuple); +	if (tuple->TupleData[1] != ETH_ALEN) { +		dev_warn(&p_dev->dev, "Invalid header for LAN_NODE_ID\n"); +		return -EINVAL;  	} +	for (i = 0; i < 6; i++) +		dev->dev_addr[i] = tuple->TupleData[i+2]; +	return 0; +}; + +/** + * pcmcia_get_mac_from_cis() - read out MAC address from CISTPL_FUNCE + * @p_dev:	the struct pcmcia_device for which we want the address. + * @dev:	a properly prepared struct net_device to store the info to. + * + * pcmcia_get_mac_from_cis() reads out the hardware MAC address from + * CISTPL_FUNCE and stores it into struct net_device *dev->dev_addr which + * must be set up properly by the driver (see examples!). + */ +int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, struct net_device *dev) +{ +	return pcmcia_loop_tuple(p_dev, CISTPL_FUNCE, pcmcia_do_get_mac, dev); +}; +EXPORT_SYMBOL(pcmcia_get_mac_from_cis); -	return ret; -} -EXPORT_SYMBOL(pcmcia_loop_config); diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 70a33468bcd..e1741cd875a 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -213,7 +213,8 @@ static irqreturn_t pd6729_interrupt(int irq, void *dev)  			if (csc & I365_CSC_DETECT) {  				events |= SS_DETECT; -				dprintk("Card detected in socket %i!\n", i); +				dev_vdbg(&socket[i].socket.dev, +					"Card detected in socket %i!\n", i);  			}  			if (indirect_read(&socket[i], I365_INTCTL) @@ -331,11 +332,11 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)  	reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */  	if (state->flags & SS_PWR_AUTO) { -		dprintk("Auto power\n"); +		dev_dbg(&sock->dev, "Auto power\n");  		reg |= I365_PWR_AUTO;	/* automatic power mngmnt */  	}  	if (state->flags & SS_OUTPUT_ENA) { -		dprintk("Power Enabled\n"); +		dev_dbg(&sock->dev, "Power Enabled\n");  		reg |= I365_PWR_OUT;	/* enable power */  	} @@ -343,40 +344,44 @@ static int pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)  	case 0:  		break;  	case 33: -		dprintk("setting voltage to Vcc to 3.3V on socket %i\n", +		dev_dbg(&sock->dev, +			"setting voltage to Vcc to 3.3V on socket %i\n",  			socket->number);  		reg |= I365_VCC_5V;  		indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);  		break;  	case 50: -		dprintk("setting voltage to Vcc to 5V on socket %i\n", +		dev_dbg(&sock->dev, +			"setting voltage to Vcc to 5V on socket %i\n",  			socket->number);  		reg |= I365_VCC_5V;  		indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);  		break;  	default: -		dprintk("pd6729: pd6729_set_socket called with " -				"invalid VCC power value: %i\n", -			state->Vcc); +		dev_dbg(&sock->dev, +			"pd6729_set_socket called with invalid VCC power " +			"value: %i\n", state->Vcc);  		return -EINVAL;  	}  	switch (state->Vpp) {  	case 0: -		dprintk("not setting Vpp on socket %i\n", socket->number); +		dev_dbg(&sock->dev, "not setting Vpp on socket %i\n", +			socket->number);  		break;  	case 33:  	case 50: -		dprintk("setting Vpp to Vcc for socket %i\n", socket->number); +		dev_dbg(&sock->dev, "setting Vpp to Vcc for socket %i\n", +			socket->number);  		reg |= I365_VPP1_5V;  		break;  	case 120: -		dprintk("setting Vpp to 12.0\n"); +		dev_dbg(&sock->dev, "setting Vpp to 12.0\n");  		reg |= I365_VPP1_12V;  		break;  	default: -		dprintk("pd6729: pd6729_set_socket called with invalid VPP power value: %i\n", -			state->Vpp); +		dev_dbg(&sock->dev, "pd6729: pd6729_set_socket called with " +			"invalid VPP power value: %i\n", state->Vpp);  		return -EINVAL;  	} @@ -438,7 +443,7 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock,  	/* Check error conditions */  	if (map > 1) { -		dprintk("pd6729_set_io_map with invalid map"); +		dev_dbg(&sock->dev, "pd6729_set_io_map with invalid map\n");  		return -EINVAL;  	} @@ -446,7 +451,7 @@ static int pd6729_set_io_map(struct pcmcia_socket *sock,  	if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map))  		indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map)); -	/* dprintk("set_io_map: Setting range to %x - %x\n", +	/* dev_dbg(&sock->dev, "set_io_map: Setting range to %x - %x\n",  	   io->start, io->stop);*/  	/* write the new values */ @@ -478,12 +483,12 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock,  	map = mem->map;  	if (map > 4) { -		printk("pd6729_set_mem_map: invalid map"); +		dev_warn(&sock->dev, "invalid map requested\n");  		return -EINVAL;  	}  	if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) { -		printk("pd6729_set_mem_map: invalid address / speed"); +		dev_warn(&sock->dev, "invalid invalid address / speed\n");  		return -EINVAL;  	} @@ -529,12 +534,12 @@ static int pd6729_set_mem_map(struct pcmcia_socket *sock,  	if (mem->flags & MAP_WRPROT)  		i |= I365_MEM_WRPROT;  	if (mem->flags & MAP_ATTRIB) { -		/* dprintk("requesting attribute memory for socket %i\n", -			socket->number);*/ +		/* dev_dbg(&sock->dev, "requesting attribute memory for " +		   "socket %i\n", socket->number);*/  		i |= I365_MEM_REG;  	} else { -		/* dprintk("requesting normal memory for socket %i\n", -			socket->number);*/ +		/* dev_dbg(&sock->dev, "requesting normal memory for " +		   "socket %i\n", socket->number);*/  	}  	indirect_write16(socket, base + I365_W_OFF, i); @@ -577,7 +582,7 @@ static struct pccard_operations pd6729_operations = {  static irqreturn_t pd6729_test(int irq, void *dev)  { -	dprintk("-> hit on irq %d\n", irq); +	pr_devel("-> hit on irq %d\n", irq);  	return IRQ_HANDLED;  } @@ -642,13 +647,13 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,  		goto err_out_free_mem;  	if (!pci_resource_start(dev, 0)) { -		printk(KERN_INFO "pd6729: refusing to load the driver " -				 "as the io_base is 0.\n"); +		dev_warn(&dev->dev, "refusing to load the driver as the " +			"io_base is NULL.\n");  		goto err_out_free_mem;  	} -	printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge " -		"at 0x%llx on irq %d\n", +	dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx " +		"on irq %d\n",  		(unsigned long long)pci_resource_start(dev, 0), dev->irq);   	/*  	 * Since we have no memory BARs some firmware may not @@ -656,14 +661,14 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,  	 */  	pci_read_config_byte(dev, PCI_COMMAND, &configbyte);  	if (!(configbyte & PCI_COMMAND_MEMORY)) { -		printk(KERN_DEBUG "pd6729: Enabling PCI_COMMAND_MEMORY.\n"); +		dev_dbg(&dev->dev, "pd6729: Enabling PCI_COMMAND_MEMORY.\n");  		configbyte |= PCI_COMMAND_MEMORY;  		pci_write_config_byte(dev, PCI_COMMAND, configbyte);  	}  	ret = pci_request_regions(dev, "pd6729");  	if (ret) { -		printk(KERN_INFO "pd6729: pci request region failed.\n"); +		dev_warn(&dev->dev, "pci request region failed.\n");  		goto err_out_disable;  	} @@ -672,7 +677,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,  	mask = pd6729_isa_scan();  	if (irq_mode == 0 && mask == 0) { -		printk(KERN_INFO "pd6729: no ISA interrupt is available.\n"); +		dev_warn(&dev->dev, "no ISA interrupt is available.\n");  		goto err_out_free_res;  	} @@ -697,8 +702,8 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,  		/* Register the interrupt handler */  		if ((ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED,  							"pd6729", socket))) { -			printk(KERN_ERR "pd6729: Failed to register irq %d, " -							"aborting\n", dev->irq); +			dev_err(&dev->dev, "Failed to register irq %d\n", +				dev->irq);  			goto err_out_free_res;  		}  	} else { @@ -713,8 +718,7 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,  	for (i = 0; i < MAX_SOCKETS; i++) {  		ret = pcmcia_register_socket(&socket[i].socket);  		if (ret) { -			printk(KERN_INFO "pd6729: pcmcia_register_socket " -					       "failed.\n"); +			dev_warn(&dev->dev, "pcmcia_register_socket failed.\n");  			for (j = 0; j < i ; j++)  				pcmcia_unregister_socket(&socket[j].socket);  			goto err_out_free_res2; diff --git a/drivers/pcmcia/pd6729.h b/drivers/pcmcia/pd6729.h index f392e458cdf..41418d394c5 100644 --- a/drivers/pcmcia/pd6729.h +++ b/drivers/pcmcia/pd6729.h @@ -1,13 +1,6 @@  #ifndef _INCLUDE_GUARD_PD6729_H_  #define _INCLUDE_GUARD_PD6729_H_ -/* Debuging defines */ -#ifdef NOTRACE -#define dprintk(fmt, args...) printk(fmt , ## args) -#else -#define dprintk(fmt, args...) do {} while (0) -#endif -  /* Flags for I365_GENCTL */  #define I365_DF_VS1		0x40	/* DF-step Voltage Sense */  #define I365_DF_VS2		0x80 diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c index 0e35acb1366..84dde7768ad 100644 --- a/drivers/pcmcia/pxa2xx_base.c +++ b/drivers/pcmcia/pxa2xx_base.c @@ -228,9 +228,43 @@ static const char *skt_names[] = {  #define SKT_DEV_INFO_SIZE(n) \  	(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) +int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt) +{ +	skt->res_skt.start = _PCMCIA(skt->nr); +	skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; +	skt->res_skt.name = skt_names[skt->nr]; +	skt->res_skt.flags = IORESOURCE_MEM; + +	skt->res_io.start = _PCMCIAIO(skt->nr); +	skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; +	skt->res_io.name = "io"; +	skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + +	skt->res_mem.start = _PCMCIAMem(skt->nr); +	skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; +	skt->res_mem.name = "memory"; +	skt->res_mem.flags = IORESOURCE_MEM; + +	skt->res_attr.start = _PCMCIAAttr(skt->nr); +	skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; +	skt->res_attr.name = "attribute"; +	skt->res_attr.flags = IORESOURCE_MEM; + +	return soc_pcmcia_add_one(skt); +} + +void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) +{ +	/* Provide our PXA2xx specific timing routines. */ +	ops->set_timing  = pxa2xx_pcmcia_set_timing; +#ifdef CONFIG_CPU_FREQ +	ops->frequency_change = pxa2xx_pcmcia_frequency_change; +#endif +} +  int __pxa2xx_drv_pcmcia_probe(struct device *dev)  { -	int i, ret; +	int i, ret = 0;  	struct pcmcia_low_level *ops;  	struct skt_dev_info *sinfo;  	struct soc_pcmcia_socket *skt; @@ -240,6 +274,8 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev)  	ops = (struct pcmcia_low_level *)dev->platform_data; +	pxa2xx_drv_pcmcia_ops(ops); +  	sinfo = kzalloc(SKT_DEV_INFO_SIZE(ops->nr), GFP_KERNEL);  	if (!sinfo)  		return -ENOMEM; @@ -250,40 +286,25 @@ int __pxa2xx_drv_pcmcia_probe(struct device *dev)  	for (i = 0; i < ops->nr; i++) {  		skt = &sinfo->skt[i]; -		skt->nr		= ops->first + i; -		skt->irq	= NO_IRQ; +		skt->nr = ops->first + i; +		skt->ops = ops; +		skt->socket.owner = ops->owner; +		skt->socket.dev.parent = dev; +		skt->socket.pci_irq = NO_IRQ; -		skt->res_skt.start	= _PCMCIA(skt->nr); -		skt->res_skt.end	= _PCMCIA(skt->nr) + PCMCIASp - 1; -		skt->res_skt.name	= skt_names[skt->nr]; -		skt->res_skt.flags	= IORESOURCE_MEM; - -		skt->res_io.start	= _PCMCIAIO(skt->nr); -		skt->res_io.end		= _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; -		skt->res_io.name	= "io"; -		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY; - -		skt->res_mem.start	= _PCMCIAMem(skt->nr); -		skt->res_mem.end	= _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; -		skt->res_mem.name	= "memory"; -		skt->res_mem.flags	= IORESOURCE_MEM; - -		skt->res_attr.start	= _PCMCIAAttr(skt->nr); -		skt->res_attr.end	= _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; -		skt->res_attr.name	= "attribute"; -		skt->res_attr.flags	= IORESOURCE_MEM; +		ret = pxa2xx_drv_pcmcia_add_one(skt); +		if (ret) +			break;  	} -	/* Provide our PXA2xx specific timing routines. */ -	ops->set_timing  = pxa2xx_pcmcia_set_timing; -#ifdef CONFIG_CPU_FREQ -	ops->frequency_change = pxa2xx_pcmcia_frequency_change; -#endif - -	ret = soc_common_drv_pcmcia_probe(dev, ops, sinfo); - -	if (!ret) +	if (ret) { +		while (--i >= 0) +			soc_pcmcia_remove_one(&sinfo->skt[i]); +		kfree(sinfo); +	} else {  		pxa2xx_configure_sockets(dev); +		dev_set_drvdata(dev, sinfo); +	}  	return ret;  } @@ -297,7 +318,16 @@ static int pxa2xx_drv_pcmcia_probe(struct platform_device *dev)  static int pxa2xx_drv_pcmcia_remove(struct platform_device *dev)  { -	return soc_common_drv_pcmcia_remove(&dev->dev); +	struct skt_dev_info *sinfo = platform_get_drvdata(dev); +	int i; + +	platform_set_drvdata(dev, NULL); + +	for (i = 0; i < sinfo->nskt; i++) +		soc_pcmcia_remove_one(&sinfo->skt[i]); + +	kfree(sinfo); +	return 0;  }  static int pxa2xx_drv_pcmcia_suspend(struct device *dev) diff --git a/drivers/pcmcia/pxa2xx_base.h b/drivers/pcmcia/pxa2xx_base.h index 235d681652c..cb5efaec886 100644 --- a/drivers/pcmcia/pxa2xx_base.h +++ b/drivers/pcmcia/pxa2xx_base.h @@ -1,3 +1,6 @@  /* temporary measure */  extern int __pxa2xx_drv_pcmcia_probe(struct device *); +int pxa2xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt); +void pxa2xx_drv_pcmcia_ops(struct pcmcia_low_level *ops); + diff --git a/drivers/pcmcia/pxa2xx_cm_x255.c b/drivers/pcmcia/pxa2xx_cm_x255.c index 5143a760153..05913d0bbdb 100644 --- a/drivers/pcmcia/pxa2xx_cm_x255.c +++ b/drivers/pcmcia/pxa2xx_cm_x255.c @@ -44,7 +44,7 @@ static int cmx255_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  		return ret;  	gpio_direction_output(GPIO_PCMCIA_RESET, 0); -	skt->irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT; +	skt->socket.pci_irq = skt->nr == 0 ? PCMCIA_S0_RDYINT : PCMCIA_S1_RDYINT;  	ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  	if (!ret)  		gpio_free(GPIO_PCMCIA_RESET); diff --git a/drivers/pcmcia/pxa2xx_cm_x270.c b/drivers/pcmcia/pxa2xx_cm_x270.c index a7b943d01e3..5662646b84d 100644 --- a/drivers/pcmcia/pxa2xx_cm_x270.c +++ b/drivers/pcmcia/pxa2xx_cm_x270.c @@ -38,7 +38,7 @@ static int cmx270_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  		return ret;  	gpio_direction_output(GPIO_PCMCIA_RESET, 0); -	skt->irq = PCMCIA_S0_RDYINT; +	skt->socket.pci_irq = PCMCIA_S0_RDYINT;  	ret = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  	if (!ret)  		gpio_free(GPIO_PCMCIA_RESET); diff --git a/drivers/pcmcia/pxa2xx_e740.c b/drivers/pcmcia/pxa2xx_e740.c index d09c0dc4a31..8bfbd4dca13 100644 --- a/drivers/pcmcia/pxa2xx_e740.c +++ b/drivers/pcmcia/pxa2xx_e740.c @@ -38,7 +38,7 @@ static struct pcmcia_irqs cd_irqs[] = {  static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  { -	skt->irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0) : +	skt->socket.pci_irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0) :  				IRQ_GPIO(GPIO_E740_PCMCIA_RDY1);  	return soc_pcmcia_request_irqs(skt, &cd_irqs[skt->nr], 1); diff --git a/drivers/pcmcia/pxa2xx_lubbock.c b/drivers/pcmcia/pxa2xx_lubbock.c index 6cbb1b1f7cf..b9f8c8fb42b 100644 --- a/drivers/pcmcia/pxa2xx_lubbock.c +++ b/drivers/pcmcia/pxa2xx_lubbock.c @@ -32,6 +32,7 @@ static int  lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,  				const socket_state_t *state)  { +	struct sa1111_pcmcia_socket *s = to_skt(skt);  	unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set;  	int ret = 0; @@ -149,7 +150,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,  	if (ret == 0) {  		lubbock_set_misc_wr(misc_mask, misc_set); -		sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); +		sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);  	}  #if 1 @@ -175,7 +176,7 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,  			 * Switch to 5V,  Configure socket with 5V voltage  			 */  			lubbock_set_misc_wr(misc_mask, 0); -			sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, 0); +			sa1111_set_io(s->dev, pa_dwr_mask, 0);  			/*  			 * It takes about 100ms to turn off Vcc. @@ -200,12 +201,8 @@ lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,  static struct pcmcia_low_level lubbock_pcmcia_ops = {  	.owner			= THIS_MODULE, -	.hw_init		= sa1111_pcmcia_hw_init, -	.hw_shutdown		= sa1111_pcmcia_hw_shutdown, -	.socket_state		= sa1111_pcmcia_socket_state,  	.configure_socket	= lubbock_pcmcia_configure_socket,  	.socket_init		= sa1111_pcmcia_socket_init, -	.socket_suspend		= sa1111_pcmcia_socket_suspend,  	.first			= 0,  	.nr			= 2,  }; @@ -228,8 +225,9 @@ int pcmcia_lubbock_init(struct sa1111_dev *sadev)  		/* Set CF Socket 1 power to standby mode. */  		lubbock_set_misc_wr((1 << 15) | (1 << 14), 0); -		sadev->dev.platform_data = &lubbock_pcmcia_ops; -		ret = __pxa2xx_drv_pcmcia_probe(&sadev->dev); +		pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops); +		ret = sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops, +				pxa2xx_drv_pcmcia_add_one);  	}  	return ret; diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 1138551ba8f..92016fe932b 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c @@ -44,7 +44,7 @@ static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  	 * before we enable them as outputs.  	 */ -	skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ; +	skt->socket.pci_irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ;  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  } diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c index 5ba9b3664a0..6fb6f7f0672 100644 --- a/drivers/pcmcia/pxa2xx_palmld.c +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -45,7 +45,7 @@ static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  	if (ret)  		goto err4; -	skt->irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY); +	skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY);  	return 0;  err4: diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c index e07b5c51ec5..b07b247a399 100644 --- a/drivers/pcmcia/pxa2xx_palmtx.c +++ b/drivers/pcmcia/pxa2xx_palmtx.c @@ -53,7 +53,7 @@ static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  	if (ret)  		goto err5; -	skt->irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY); +	skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY);  	return 0;  err5: diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index bc43f78f6f0..0ea3b29440e 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -66,7 +66,7 @@ static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  		}  	} -	skt->irq = SCOOP_DEV[skt->nr].irq; +	skt->socket.pci_irq = SCOOP_DEV[skt->nr].irq;  	return 0;  } diff --git a/drivers/pcmcia/pxa2xx_trizeps4.c b/drivers/pcmcia/pxa2xx_trizeps4.c index e0e5cb339b4..b7e596620db 100644 --- a/drivers/pcmcia/pxa2xx_trizeps4.c +++ b/drivers/pcmcia/pxa2xx_trizeps4.c @@ -53,7 +53,7 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  			gpio_free(GPIO_PRDY);  			return -EINVAL;  		} -		skt->irq = IRQ_GPIO(GPIO_PRDY); +		skt->socket.pci_irq = IRQ_GPIO(GPIO_PRDY);  		break;  #ifndef CONFIG_MACH_TRIZEPS_CONXS @@ -63,7 +63,7 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  		break;  	}  	/* release the reset of this card */ -	pr_debug("%s: sock %d irq %d\n", __func__, skt->nr, skt->irq); +	pr_debug("%s: sock %d irq %d\n", __func__, skt->nr, skt->socket.pci_irq);  	/* supplementory irqs for the socket */  	for (i = 0; i < ARRAY_SIZE(irqs); i++) { diff --git a/drivers/pcmcia/pxa2xx_viper.c b/drivers/pcmcia/pxa2xx_viper.c index 17871360fe9..27be2e154df 100644 --- a/drivers/pcmcia/pxa2xx_viper.c +++ b/drivers/pcmcia/pxa2xx_viper.c @@ -40,7 +40,7 @@ static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  {  	unsigned long flags; -	skt->irq = gpio_to_irq(VIPER_CF_RDY_GPIO); +	skt->socket.pci_irq = gpio_to_irq(VIPER_CF_RDY_GPIO);  	if (gpio_request(VIPER_CF_CD_GPIO, "CF detect"))  		goto err_request_cd; diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index e592e0e0d7e..de0e770ce6a 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -18,6 +18,7 @@  #include <pcmcia/cs_types.h>  #include <pcmcia/ss.h>  #include <pcmcia/cs.h> +#include <pcmcia/cistpl.h>  #include "cs_internal.h" diff --git a/drivers/pcmcia/sa1100_assabet.c b/drivers/pcmcia/sa1100_assabet.c index ac8aa09ba0d..fd013a1ef47 100644 --- a/drivers/pcmcia/sa1100_assabet.c +++ b/drivers/pcmcia/sa1100_assabet.c @@ -27,7 +27,7 @@ static struct pcmcia_irqs irqs[] = {  static int assabet_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  { -	skt->irq = ASSABET_IRQ_GPIO_CF_IRQ; +	skt->socket.pci_irq = ASSABET_IRQ_GPIO_CF_IRQ;  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  } diff --git a/drivers/pcmcia/sa1100_badge4.c b/drivers/pcmcia/sa1100_badge4.c index 1ca9737ea79..1ce53f493be 100644 --- a/drivers/pcmcia/sa1100_badge4.c +++ b/drivers/pcmcia/sa1100_badge4.c @@ -127,13 +127,10 @@ badge4_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state  static struct pcmcia_low_level badge4_pcmcia_ops = {  	.owner			= THIS_MODULE, -	.hw_init		= sa1111_pcmcia_hw_init, -	.hw_shutdown		= sa1111_pcmcia_hw_shutdown, -	.socket_state		= sa1111_pcmcia_socket_state,  	.configure_socket	= badge4_pcmcia_configure_socket, -  	.socket_init		= sa1111_pcmcia_socket_init, -	.socket_suspend		= sa1111_pcmcia_socket_suspend, +	.first			= 0, +	.nr			= 2,  };  int pcmcia_badge4_init(struct device *dev) @@ -146,7 +143,9 @@ int pcmcia_badge4_init(struct device *dev)  		       __func__,  		       badge4_pcmvcc, badge4_pcmvpp, badge4_cfvcc); -		ret = sa11xx_drv_pcmcia_probe(dev, &badge4_pcmcia_ops, 0, 2); +		sa11xx_drv_pcmcia_ops(&badge4_pcmcia_ops); +		ret = sa1111_pcmcia_add(dev, &badge4_pcmcia_ops, +				sa11xx_drv_pcmcia_add_one);  	}  	return ret; diff --git a/drivers/pcmcia/sa1100_cerf.c b/drivers/pcmcia/sa1100_cerf.c index 63e6bc431a0..9bf088b1727 100644 --- a/drivers/pcmcia/sa1100_cerf.c +++ b/drivers/pcmcia/sa1100_cerf.c @@ -27,7 +27,7 @@ static struct pcmcia_irqs irqs[] = {  static int cerf_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  { -	skt->irq = CERF_IRQ_GPIO_CF_IRQ; +	skt->socket.pci_irq = CERF_IRQ_GPIO_CF_IRQ;  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  } diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index 2d0e9975153..11cc3ba1260 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -83,7 +83,16 @@ static int sa11x0_drv_pcmcia_probe(struct platform_device *dev)  static int sa11x0_drv_pcmcia_remove(struct platform_device *dev)  { -	return soc_common_drv_pcmcia_remove(&dev->dev); +	struct skt_dev_info *sinfo = platform_get_drvdata(dev); +	int i; + +	platform_set_drvdata(dev, NULL); + +	for (i = 0; i < sinfo->nskt; i++) +		soc_pcmcia_remove_one(&sinfo->skt[i]); + +	kfree(sinfo); +	return 0;  }  static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev, diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c index 0cc3748f375..3a121ac697d 100644 --- a/drivers/pcmcia/sa1100_h3600.c +++ b/drivers/pcmcia/sa1100_h3600.c @@ -25,8 +25,8 @@ static struct pcmcia_irqs irqs[] = {  static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  { -	skt->irq = skt->nr ? IRQ_GPIO_H3600_PCMCIA_IRQ1 -			   : IRQ_GPIO_H3600_PCMCIA_IRQ0; +	skt->socket.pci_irq = skt->nr ? IRQ_GPIO_H3600_PCMCIA_IRQ1 +				      : IRQ_GPIO_H3600_PCMCIA_IRQ0;  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c index 7eedb42f800..6bcabee6bde 100644 --- a/drivers/pcmcia/sa1100_jornada720.c +++ b/drivers/pcmcia/sa1100_jornada720.c @@ -22,25 +22,10 @@  #define SOCKET1_POWER	(GPIO_GPIO1 | GPIO_GPIO3)  #define SOCKET1_3V	GPIO_GPIO3 -static int jornada720_pcmcia_hw_init(struct soc_pcmcia_socket *skt) -{ -	unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; - -	/* -	* What is all this crap for? -	*/ -	GRER |= 0x00000002; -	/* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */ -	sa1111_set_io_dir(SA1111_DEV(skt->dev), pin, 0, 0); -	sa1111_set_io(SA1111_DEV(skt->dev), pin, 0); -	sa1111_set_sleep_io(SA1111_DEV(skt->dev), pin, 0); - -	return sa1111_pcmcia_hw_init(skt); -} -  static int  jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)  { +	struct sa1111_pcmcia_socket *s = to_skt(skt);  	unsigned int pa_dwr_mask, pa_dwr_set;  	int ret; @@ -97,7 +82,7 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s  		unsigned long flags;  		local_irq_save(flags); -		sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); +		sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);  		local_irq_restore(flags);  	} @@ -106,21 +91,30 @@ jornada720_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s  static struct pcmcia_low_level jornada720_pcmcia_ops = {  	.owner			= THIS_MODULE, -	.hw_init		= jornada720_pcmcia_hw_init, -	.hw_shutdown		= sa1111_pcmcia_hw_shutdown, -	.socket_state		= sa1111_pcmcia_socket_state,  	.configure_socket	= jornada720_pcmcia_configure_socket, -  	.socket_init		= sa1111_pcmcia_socket_init, -	.socket_suspend		= sa1111_pcmcia_socket_suspend, +	.first			= 0, +	.nr			= 2,  };  int __devinit pcmcia_jornada720_init(struct device *dev)  {  	int ret = -ENODEV; -	if (machine_is_jornada720()) -		ret = sa11xx_drv_pcmcia_probe(dev, &jornada720_pcmcia_ops, 0, 2); +	if (machine_is_jornada720()) { +		unsigned int pin = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3; + +		GRER |= 0x00000002; + +		/* Set GPIO_A<3:1> to be outputs for PCMCIA/CF power controller: */ +		sa1111_set_io_dir(dev, pin, 0, 0); +		sa1111_set_io(dev, pin, 0); +		sa1111_set_sleep_io(dev, pin, 0); + +		sa11xx_drv_pcmcia_ops(&jornada720_pcmcia_ops); +		ret = sa1111_pcmcia_add(dev, &jornada720_pcmcia_ops, +				sa11xx_drv_pcmcia_add_one); +	}  	return ret;  } diff --git a/drivers/pcmcia/sa1100_neponset.c b/drivers/pcmcia/sa1100_neponset.c index 0c76d337815..c95639b5f2a 100644 --- a/drivers/pcmcia/sa1100_neponset.c +++ b/drivers/pcmcia/sa1100_neponset.c @@ -43,6 +43,7 @@  static int  neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)  { +	struct sa1111_pcmcia_socket *s = to_skt(skt);  	unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;  	int ret; @@ -99,7 +100,7 @@ neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_sta  		NCR_0 = (NCR_0 & ~ncr_mask) | ncr_set;  		local_irq_restore(flags); -		sa1111_set_io(SA1111_DEV(skt->dev), pa_dwr_mask, pa_dwr_set); +		sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);  	}  	return 0; @@ -115,12 +116,10 @@ static void neponset_pcmcia_socket_init(struct soc_pcmcia_socket *skt)  static struct pcmcia_low_level neponset_pcmcia_ops = {  	.owner			= THIS_MODULE, -	.hw_init		= sa1111_pcmcia_hw_init, -	.hw_shutdown		= sa1111_pcmcia_hw_shutdown, -	.socket_state		= sa1111_pcmcia_socket_state,  	.configure_socket	= neponset_pcmcia_configure_socket,  	.socket_init		= neponset_pcmcia_socket_init, -	.socket_suspend 	= sa1111_pcmcia_socket_suspend, +	.first			= 0, +	.nr			= 2,  };  int pcmcia_neponset_init(struct sa1111_dev *sadev) @@ -135,7 +134,9 @@ int pcmcia_neponset_init(struct sa1111_dev *sadev)  		sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);  		sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);  		sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0); -		ret = sa11xx_drv_pcmcia_probe(&sadev->dev, &neponset_pcmcia_ops, 0, 2); +		sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops); +		ret = sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops, +				sa11xx_drv_pcmcia_add_one);  	}  	return ret; diff --git a/drivers/pcmcia/sa1100_shannon.c b/drivers/pcmcia/sa1100_shannon.c index 46d8c1977c2..c4d51867a05 100644 --- a/drivers/pcmcia/sa1100_shannon.c +++ b/drivers/pcmcia/sa1100_shannon.c @@ -28,7 +28,7 @@ static int shannon_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  	GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 |   		  SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); -	skt->irq = skt->nr ? SHANNON_IRQ_GPIO_RDY_1 : SHANNON_IRQ_GPIO_RDY_0; +	skt->socket.pci_irq = skt->nr ? SHANNON_IRQ_GPIO_RDY_1 : SHANNON_IRQ_GPIO_RDY_0;  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  } diff --git a/drivers/pcmcia/sa1100_simpad.c b/drivers/pcmcia/sa1100_simpad.c index 33a08ae09fd..05bd504e6f1 100644 --- a/drivers/pcmcia/sa1100_simpad.c +++ b/drivers/pcmcia/sa1100_simpad.c @@ -28,7 +28,7 @@ static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  	clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); -	skt->irq = IRQ_GPIO_CF_IRQ; +	skt->socket.pci_irq = IRQ_GPIO_CF_IRQ;  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  } diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c index 4be4e172ffa..de6bc333d29 100644 --- a/drivers/pcmcia/sa1111_generic.c +++ b/drivers/pcmcia/sa1111_generic.c @@ -28,23 +28,20 @@ static struct pcmcia_irqs irqs[] = {  	{ 1, IRQ_S1_BVD1_STSCHG, "SA1111 CF BVD1"            },  }; -int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt) +static int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt)  { -	if (skt->irq == NO_IRQ) -		skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT; -  	return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));  } -void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) +static void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)  {  	soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));  }  void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)  { -	struct sa1111_dev *sadev = SA1111_DEV(skt->dev); -	unsigned long status = sa1111_readl(sadev->mapbase + SA1111_PCSR); +	struct sa1111_pcmcia_socket *s = to_skt(skt); +	unsigned long status = sa1111_readl(s->dev->mapbase + SA1111_PCSR);  	switch (skt->nr) {  	case 0: @@ -71,7 +68,7 @@ void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_sta  int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)  { -	struct sa1111_dev *sadev = SA1111_DEV(skt->dev); +	struct sa1111_pcmcia_socket *s = to_skt(skt);  	unsigned int pccr_skt_mask, pccr_set_mask, val;  	unsigned long flags; @@ -100,10 +97,10 @@ int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s  		pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;  	local_irq_save(flags); -	val = sa1111_readl(sadev->mapbase + SA1111_PCCR); +	val = sa1111_readl(s->dev->mapbase + SA1111_PCCR);  	val &= ~pccr_skt_mask;  	val |= pccr_set_mask & pccr_skt_mask; -	sa1111_writel(val, sadev->mapbase + SA1111_PCCR); +	sa1111_writel(val, s->dev->mapbase + SA1111_PCCR);  	local_irq_restore(flags);  	return 0; @@ -114,15 +111,51 @@ void sa1111_pcmcia_socket_init(struct soc_pcmcia_socket *skt)  	soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));  } -void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) +static void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)  {  	soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));  } +int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, +	int (*add)(struct soc_pcmcia_socket *)) +{ +	struct sa1111_pcmcia_socket *s; +	int i, ret = 0; + +	ops->hw_init = sa1111_pcmcia_hw_init; +	ops->hw_shutdown = sa1111_pcmcia_hw_shutdown; +	ops->socket_state = sa1111_pcmcia_socket_state; +	ops->socket_suspend = sa1111_pcmcia_socket_suspend; + +	for (i = 0; i < ops->nr; i++) { +		s = kzalloc(sizeof(*s), GFP_KERNEL); +		if (!s) +			return -ENOMEM; + +		s->soc.nr = ops->first + i; +		s->soc.ops = ops; +		s->soc.socket.owner = ops->owner; +		s->soc.socket.dev.parent = &dev->dev; +		s->soc.socket.pci_irq = s->soc.nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT; +		s->dev = dev; + +		ret = add(&s->soc); +		if (ret == 0) { +			s->next = dev_get_drvdata(&dev->dev); +			dev_set_drvdata(&dev->dev, s); +		} else +			kfree(s); +	} + +	return ret; +} +  static int pcmcia_probe(struct sa1111_dev *dev)  {  	void __iomem *base; +	dev_set_drvdata(&dev->dev, NULL); +  	if (!request_mem_region(dev->res.start, 512,  				SA1111_DRIVER_NAME(dev)))  		return -EBUSY; @@ -152,7 +185,15 @@ static int pcmcia_probe(struct sa1111_dev *dev)  static int __devexit pcmcia_remove(struct sa1111_dev *dev)  { -	soc_common_drv_pcmcia_remove(&dev->dev); +	struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev); + +	dev_set_drvdata(&dev->dev, NULL); + +	for (; next = s->next, s; s = next) { +		soc_pcmcia_remove_one(&s->soc); +		kfree(s); +	} +  	release_mem_region(dev->res.start, 512);  	return 0;  } diff --git a/drivers/pcmcia/sa1111_generic.h b/drivers/pcmcia/sa1111_generic.h index 10ced4a210d..02dc8577cda 100644 --- a/drivers/pcmcia/sa1111_generic.h +++ b/drivers/pcmcia/sa1111_generic.h @@ -1,12 +1,23 @@  #include "soc_common.h"  #include "sa11xx_base.h" -extern int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *); -extern void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *); +struct sa1111_pcmcia_socket { +	struct soc_pcmcia_socket soc; +	struct sa1111_dev *dev; +	struct sa1111_pcmcia_socket *next; +}; + +static inline struct sa1111_pcmcia_socket *to_skt(struct soc_pcmcia_socket *s) +{ +	return container_of(s, struct sa1111_pcmcia_socket, soc); +} + +int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, +	int (*add)(struct soc_pcmcia_socket *)); +  extern void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *, struct pcmcia_state *);  extern int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *, const socket_state_t *);  extern void sa1111_pcmcia_socket_init(struct soc_pcmcia_socket *); -extern void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *);  extern int pcmcia_badge4_init(struct device *);  extern int pcmcia_jornada720_init(struct device *); diff --git a/drivers/pcmcia/sa11xx_base.c b/drivers/pcmcia/sa11xx_base.c index e15d59f2d8a..fc9a6527019 100644 --- a/drivers/pcmcia/sa11xx_base.c +++ b/drivers/pcmcia/sa11xx_base.c @@ -171,47 +171,34 @@ static const char *skt_names[] = {  #define SKT_DEV_INFO_SIZE(n) \  	(sizeof(struct skt_dev_info) + (n)*sizeof(struct soc_pcmcia_socket)) -int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, -			    int first, int nr) +int sa11xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt)  { -	struct skt_dev_info *sinfo; -	struct soc_pcmcia_socket *skt; -	int i; +	skt->res_skt.start = _PCMCIA(skt->nr); +	skt->res_skt.end = _PCMCIA(skt->nr) + PCMCIASp - 1; +	skt->res_skt.name = skt_names[skt->nr]; +	skt->res_skt.flags = IORESOURCE_MEM; -	sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); -	if (!sinfo) -		return -ENOMEM; +	skt->res_io.start = _PCMCIAIO(skt->nr); +	skt->res_io.end = _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; +	skt->res_io.name = "io"; +	skt->res_io.flags = IORESOURCE_MEM | IORESOURCE_BUSY; -	sinfo->nskt = nr; +	skt->res_mem.start = _PCMCIAMem(skt->nr); +	skt->res_mem.end = _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; +	skt->res_mem.name = "memory"; +	skt->res_mem.flags = IORESOURCE_MEM; -	/* Initiliaze processor specific parameters */ -	for (i = 0; i < nr; i++) { -		skt = &sinfo->skt[i]; +	skt->res_attr.start = _PCMCIAAttr(skt->nr); +	skt->res_attr.end = _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; +	skt->res_attr.name = "attribute"; +	skt->res_attr.flags = IORESOURCE_MEM; -		skt->nr		= first + i; -		skt->irq	= NO_IRQ; - -		skt->res_skt.start	= _PCMCIA(skt->nr); -		skt->res_skt.end	= _PCMCIA(skt->nr) + PCMCIASp - 1; -		skt->res_skt.name	= skt_names[skt->nr]; -		skt->res_skt.flags	= IORESOURCE_MEM; - -		skt->res_io.start	= _PCMCIAIO(skt->nr); -		skt->res_io.end		= _PCMCIAIO(skt->nr) + PCMCIAIOSp - 1; -		skt->res_io.name	= "io"; -		skt->res_io.flags	= IORESOURCE_MEM | IORESOURCE_BUSY; - -		skt->res_mem.start	= _PCMCIAMem(skt->nr); -		skt->res_mem.end	= _PCMCIAMem(skt->nr) + PCMCIAMemSp - 1; -		skt->res_mem.name	= "memory"; -		skt->res_mem.flags	= IORESOURCE_MEM; - -		skt->res_attr.start	= _PCMCIAAttr(skt->nr); -		skt->res_attr.end	= _PCMCIAAttr(skt->nr) + PCMCIAAttrSp - 1; -		skt->res_attr.name	= "attribute"; -		skt->res_attr.flags	= IORESOURCE_MEM; -	} +	return soc_pcmcia_add_one(skt); +} +EXPORT_SYMBOL(sa11xx_drv_pcmcia_add_one); +void sa11xx_drv_pcmcia_ops(struct pcmcia_low_level *ops) +{  	/*  	 * set default MECR calculation if the board specific  	 * code did not specify one... @@ -225,8 +212,48 @@ int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops,  #ifdef CONFIG_CPU_FREQ  	ops->frequency_change = sa1100_pcmcia_frequency_change;  #endif +} +EXPORT_SYMBOL(sa11xx_drv_pcmcia_ops); + +int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, +			    int first, int nr) +{ +	struct skt_dev_info *sinfo; +	struct soc_pcmcia_socket *skt; +	int i, ret = 0; + +	sa11xx_drv_pcmcia_ops(ops); + +	sinfo = kzalloc(SKT_DEV_INFO_SIZE(nr), GFP_KERNEL); +	if (!sinfo) +		return -ENOMEM; + +	sinfo->nskt = nr; + +	/* Initiliaze processor specific parameters */ +	for (i = 0; i < nr; i++) { +		skt = &sinfo->skt[i]; + +		skt->nr = first + i; +		skt->ops = ops; +		skt->socket.owner = ops->owner; +		skt->socket.dev.parent = dev; +		skt->socket.pci_irq = NO_IRQ; + +		ret = sa11xx_drv_pcmcia_add_one(skt); +		if (ret) +			break; +	} + +	if (ret) { +		while (--i >= 0) +			soc_pcmcia_remove_one(&sinfo->skt[i]); +		kfree(sinfo); +	} else { +		dev_set_drvdata(dev, sinfo); +	} -	return soc_common_drv_pcmcia_probe(dev, ops, sinfo); +	return ret;  }  EXPORT_SYMBOL(sa11xx_drv_pcmcia_probe); diff --git a/drivers/pcmcia/sa11xx_base.h b/drivers/pcmcia/sa11xx_base.h index 7bc20828052..3d76d720f46 100644 --- a/drivers/pcmcia/sa11xx_base.h +++ b/drivers/pcmcia/sa11xx_base.h @@ -118,6 +118,8 @@ static inline unsigned int sa1100_pcmcia_cmd_time(unsigned int cpu_clock_khz,  } +int sa11xx_drv_pcmcia_add_one(struct soc_pcmcia_socket *skt); +void sa11xx_drv_pcmcia_ops(struct pcmcia_low_level *ops);  extern int sa11xx_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, int first, int nr);  #endif  /* !defined(_PCMCIA_SA1100_H) */ diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index ef7e9e58782..6f1a86b43c6 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -144,10 +144,10 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat  		 */  		if (skt->irq_state != 1 && state->io_irq) {  			skt->irq_state = 1; -			set_irq_type(skt->irq, IRQ_TYPE_EDGE_FALLING); +			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);  		} else if (skt->irq_state == 1 && state->io_irq == 0) {  			skt->irq_state = 0; -			set_irq_type(skt->irq, IRQ_TYPE_NONE); +			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);  		}  		skt->cs_state = *state; @@ -492,7 +492,8 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, ch  	p+=sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);  	p+=sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp); -	p+=sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq, skt->irq); +	p+=sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq, +		skt->socket.pci_irq);  	if (skt->ops->show_timing)  		p+=skt->ops->show_timing(skt, p); @@ -574,7 +575,7 @@ void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,  EXPORT_SYMBOL(soc_pcmcia_enable_irqs); -LIST_HEAD(soc_pcmcia_sockets); +static LIST_HEAD(soc_pcmcia_sockets);  static DEFINE_MUTEX(soc_pcmcia_sockets_lock);  #ifdef CONFIG_CPU_FREQ @@ -609,177 +610,137 @@ static int soc_pcmcia_cpufreq_register(void)  				"notifier for PCMCIA (%d)\n", ret);  	return ret;  } +fs_initcall(soc_pcmcia_cpufreq_register);  static void soc_pcmcia_cpufreq_unregister(void)  {  	cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);  } +module_exit(soc_pcmcia_cpufreq_unregister); -#else -static int soc_pcmcia_cpufreq_register(void) { return 0; } -static void soc_pcmcia_cpufreq_unregister(void) {}  #endif -int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, -				struct skt_dev_info *sinfo) +void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)  { -	struct soc_pcmcia_socket *skt; -	int ret, i; -  	mutex_lock(&soc_pcmcia_sockets_lock); +	del_timer_sync(&skt->poll_timer); -	/* -	 * Initialise the per-socket structure. -	 */ -	for (i = 0; i < sinfo->nskt; i++) { -		skt = &sinfo->skt[i]; +	pcmcia_unregister_socket(&skt->socket); -		skt->socket.ops = &soc_common_pcmcia_operations; -		skt->socket.owner = ops->owner; -		skt->socket.dev.parent = dev; +	flush_scheduled_work(); -		init_timer(&skt->poll_timer); -		skt->poll_timer.function = soc_common_pcmcia_poll_event; -		skt->poll_timer.data = (unsigned long)skt; -		skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; +	skt->ops->hw_shutdown(skt); -		skt->dev	= dev; -		skt->ops	= ops; +	soc_common_pcmcia_config_skt(skt, &dead_socket); -		ret = request_resource(&iomem_resource, &skt->res_skt); -		if (ret) -			goto out_err_1; +	list_del(&skt->node); +	mutex_unlock(&soc_pcmcia_sockets_lock); -		ret = request_resource(&skt->res_skt, &skt->res_io); -		if (ret) -			goto out_err_2; +	iounmap(skt->virt_io); +	skt->virt_io = NULL; +	release_resource(&skt->res_attr); +	release_resource(&skt->res_mem); +	release_resource(&skt->res_io); +	release_resource(&skt->res_skt); +} +EXPORT_SYMBOL(soc_pcmcia_remove_one); -		ret = request_resource(&skt->res_skt, &skt->res_mem); -		if (ret) -			goto out_err_3; +int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt) +{ +	int ret; -		ret = request_resource(&skt->res_skt, &skt->res_attr); -		if (ret) -			goto out_err_4; +	init_timer(&skt->poll_timer); +	skt->poll_timer.function = soc_common_pcmcia_poll_event; +	skt->poll_timer.data = (unsigned long)skt; +	skt->poll_timer.expires = jiffies + SOC_PCMCIA_POLL_PERIOD; -		skt->virt_io = ioremap(skt->res_io.start, 0x10000); -		if (skt->virt_io == NULL) { -			ret = -ENOMEM; -			goto out_err_5; -		} +	ret = request_resource(&iomem_resource, &skt->res_skt); +	if (ret) +		goto out_err_1; -		if (list_empty(&soc_pcmcia_sockets)) -			soc_pcmcia_cpufreq_register(); +	ret = request_resource(&skt->res_skt, &skt->res_io); +	if (ret) +		goto out_err_2; -		list_add(&skt->node, &soc_pcmcia_sockets); +	ret = request_resource(&skt->res_skt, &skt->res_mem); +	if (ret) +		goto out_err_3; -		/* -		 * We initialize default socket timing here, because -		 * we are not guaranteed to see a SetIOMap operation at -		 * runtime. -		 */ -		ops->set_timing(skt); +	ret = request_resource(&skt->res_skt, &skt->res_attr); +	if (ret) +		goto out_err_4; -		ret = ops->hw_init(skt); -		if (ret) -			goto out_err_6; +	skt->virt_io = ioremap(skt->res_io.start, 0x10000); +	if (skt->virt_io == NULL) { +		ret = -ENOMEM; +		goto out_err_5; +	} -		skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; -		skt->socket.resource_ops = &pccard_static_ops; -		skt->socket.irq_mask = 0; -		skt->socket.map_size = PAGE_SIZE; -		skt->socket.pci_irq = skt->irq; -		skt->socket.io_offset = (unsigned long)skt->virt_io; +	mutex_lock(&soc_pcmcia_sockets_lock); -		skt->status = soc_common_pcmcia_skt_state(skt); +	list_add(&skt->node, &soc_pcmcia_sockets); -		ret = pcmcia_register_socket(&skt->socket); -		if (ret) -			goto out_err_7; +	/* +	 * We initialize default socket timing here, because +	 * we are not guaranteed to see a SetIOMap operation at +	 * runtime. +	 */ +	skt->ops->set_timing(skt); -		WARN_ON(skt->socket.sock != i); +	ret = skt->ops->hw_init(skt); +	if (ret) +		goto out_err_6; -		add_timer(&skt->poll_timer); +	skt->socket.ops = &soc_common_pcmcia_operations; +	skt->socket.features = SS_CAP_STATIC_MAP|SS_CAP_PCCARD; +	skt->socket.resource_ops = &pccard_static_ops; +	skt->socket.irq_mask = 0; +	skt->socket.map_size = PAGE_SIZE; +	skt->socket.io_offset = (unsigned long)skt->virt_io; -		ret = device_create_file(&skt->socket.dev, &dev_attr_status); -		if (ret) -			goto out_err_8; -	} +	skt->status = soc_common_pcmcia_skt_state(skt); -	dev_set_drvdata(dev, sinfo); -	ret = 0; -	goto out; +	ret = pcmcia_register_socket(&skt->socket); +	if (ret) +		goto out_err_7; -	do { -		skt = &sinfo->skt[i]; +	add_timer(&skt->poll_timer); + +	mutex_unlock(&soc_pcmcia_sockets_lock); + +	ret = device_create_file(&skt->socket.dev, &dev_attr_status); +	if (ret) +		goto out_err_8; + +	return ret; -		device_remove_file(&skt->socket.dev, &dev_attr_status);   out_err_8: -		del_timer_sync(&skt->poll_timer); -		pcmcia_unregister_socket(&skt->socket); +	mutex_lock(&soc_pcmcia_sockets_lock); +	del_timer_sync(&skt->poll_timer); +	pcmcia_unregister_socket(&skt->socket);   out_err_7: -		flush_scheduled_work(); +	flush_scheduled_work(); -		ops->hw_shutdown(skt); +	skt->ops->hw_shutdown(skt);   out_err_6: - 		list_del(&skt->node); -		iounmap(skt->virt_io); +	list_del(&skt->node); +	mutex_unlock(&soc_pcmcia_sockets_lock); +	iounmap(skt->virt_io);   out_err_5: -		release_resource(&skt->res_attr); +	release_resource(&skt->res_attr);   out_err_4: -		release_resource(&skt->res_mem); +	release_resource(&skt->res_mem);   out_err_3: -		release_resource(&skt->res_io); +	release_resource(&skt->res_io);   out_err_2: -		release_resource(&skt->res_skt); +	release_resource(&skt->res_skt);   out_err_1: -		i--; -	} while (i > 0); -	kfree(sinfo); - - out: -	mutex_unlock(&soc_pcmcia_sockets_lock);  	return ret;  } +EXPORT_SYMBOL(soc_pcmcia_add_one); -int soc_common_drv_pcmcia_remove(struct device *dev) -{ -	struct skt_dev_info *sinfo = dev_get_drvdata(dev); -	int i; - -	dev_set_drvdata(dev, NULL); - -	mutex_lock(&soc_pcmcia_sockets_lock); -	for (i = 0; i < sinfo->nskt; i++) { -		struct soc_pcmcia_socket *skt = &sinfo->skt[i]; - -		del_timer_sync(&skt->poll_timer); - -		pcmcia_unregister_socket(&skt->socket); - -		flush_scheduled_work(); - -		skt->ops->hw_shutdown(skt); - -		soc_common_pcmcia_config_skt(skt, &dead_socket); - -		list_del(&skt->node); -		iounmap(skt->virt_io); -		skt->virt_io = NULL; -		release_resource(&skt->res_attr); -		release_resource(&skt->res_mem); -		release_resource(&skt->res_io); -		release_resource(&skt->res_skt); -	} -	if (list_empty(&soc_pcmcia_sockets)) -		soc_pcmcia_cpufreq_unregister(); - -	mutex_unlock(&soc_pcmcia_sockets_lock); - -	kfree(sinfo); - -	return 0; -} -EXPORT_SYMBOL(soc_common_drv_pcmcia_remove); +MODULE_AUTHOR("John Dorsey <john+@cs.cmu.edu>"); +MODULE_DESCRIPTION("Linux PCMCIA Card Services: Common SoC support"); +MODULE_LICENSE("Dual MPL/GPL"); diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h index 290e143839e..e40824ce6b0 100644 --- a/drivers/pcmcia/soc_common.h +++ b/drivers/pcmcia/soc_common.h @@ -30,14 +30,12 @@ struct soc_pcmcia_socket {  	/*  	 * Info from low level handler  	 */ -	struct device		*dev;  	unsigned int		nr; -	unsigned int		irq;  	/*  	 * Core PCMCIA state  	 */ -	struct pcmcia_low_level *ops; +	const struct pcmcia_low_level *ops;  	unsigned int		status;  	socket_state_t		cs_state; @@ -135,10 +133,8 @@ extern void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt, struct pcmcia_  extern void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *, struct soc_pcmcia_timing *); -extern struct list_head soc_pcmcia_sockets; - -extern int soc_common_drv_pcmcia_probe(struct device *dev, struct pcmcia_low_level *ops, struct skt_dev_info *sinfo); -extern int soc_common_drv_pcmcia_remove(struct device *dev); +void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt); +int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt);  #ifdef CONFIG_PCMCIA_DEBUG diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 6918849d511..12c49ee135e 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -55,21 +55,6 @@  #include <pcmcia/ss.h>  #include "tcic.h" -#ifdef CONFIG_PCMCIA_DEBUG -static int pc_debug; - -module_param(pc_debug, int, 0644); -static const char version[] = -"tcic.c 1.111 2000/02/15 04:13:12 (David Hinds)"; - -#define debug(lvl, fmt, arg...) do {				\ -	if (pc_debug > (lvl))					\ -		printk(KERN_DEBUG "tcic: " fmt , ## arg);	\ -} while (0) -#else -#define debug(lvl, fmt, arg...) do { } while (0) -#endif -  MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");  MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");  MODULE_LICENSE("Dual MPL/GPL"); @@ -574,7 +559,7 @@ static irqreturn_t tcic_interrupt(int irq, void *dev)      } else  	active = 1; -    debug(2, "tcic_interrupt()\n"); +    pr_debug("tcic_interrupt()\n");      for (i = 0; i < sockets; i++) {  	psock = socket_table[i].psock; @@ -611,13 +596,13 @@ static irqreturn_t tcic_interrupt(int irq, void *dev)      }      active = 0; -    debug(2, "interrupt done\n"); +    pr_debug("interrupt done\n");      return IRQ_HANDLED;  } /* tcic_interrupt */  static void tcic_timer(u_long data)  { -    debug(2, "tcic_timer()\n"); +    pr_debug("tcic_timer()\n");      tcic_timer_pending = 0;      tcic_interrupt(0, NULL);  } /* tcic_timer */ @@ -644,7 +629,7 @@ static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)      reg = tcic_getb(TCIC_PWR);      if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))  	*value |= SS_POWERON; -    debug(1, "GetStatus(%d) = %#2.2x\n", psock, *value); +    dev_dbg(&sock->dev, "GetStatus(%d) = %#2.2x\n", psock, *value);      return 0;  } /* tcic_get_status */ @@ -656,7 +641,7 @@ static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)      u_char reg;      u_short scf1, scf2; -    debug(1, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, " +    dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "  	  "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,  	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);      tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG); @@ -731,7 +716,7 @@ static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)      u_int addr;      u_short base, len, ioctl; -    debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, " +    dev_dbg(&sock->dev, "SetIOMap(%d, %d, %#2.2x, %d ns, "  	  "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,  	  (unsigned long long)io->start, (unsigned long long)io->stop);      if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) || @@ -768,7 +753,7 @@ static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *m      u_short addr, ctl;      u_long base, len, mmap; -    debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, " +    dev_dbg(&sock->dev, "SetMemMap(%d, %d, %#2.2x, %d ns, "  	  "%#llx-%#llx, %#x)\n", psock, mem->map, mem->flags,  	  mem->speed, (unsigned long long)mem->res->start,  	  (unsigned long long)mem->res->end, mem->card_start); diff --git a/drivers/pcmcia/topic.h b/drivers/pcmcia/topic.h index edccfa5bb40..615a45a8fe8 100644 --- a/drivers/pcmcia/topic.h +++ b/drivers/pcmcia/topic.h @@ -114,22 +114,17 @@ static void topic97_zoom_video(struct pcmcia_socket *sock, int onoff)  		reg_zv |= TOPIC97_ZV_CONTROL_ENABLE;  		config_writeb(socket, TOPIC97_ZOOM_VIDEO_CONTROL, reg_zv); -		reg = config_readb(socket, TOPIC97_MISC2); -		reg |= TOPIC97_MISC2_ZV_ENABLE; -		config_writeb(socket, TOPIC97_MISC2, reg); - -		/* not sure this is needed, doc is unclear */ -#if 0  		reg = config_readb(socket, TOPIC97_AUDIO_VIDEO_SWITCH);  		reg |= TOPIC97_AVS_AUDIO_CONTROL | TOPIC97_AVS_VIDEO_CONTROL;  		config_writeb(socket, TOPIC97_AUDIO_VIDEO_SWITCH, reg); -#endif -	} -	else { +	} else {  		reg_zv &= ~TOPIC97_ZV_CONTROL_ENABLE;  		config_writeb(socket, TOPIC97_ZOOM_VIDEO_CONTROL, reg_zv); -	} +		reg = config_readb(socket, TOPIC97_AUDIO_VIDEO_SWITCH); +		reg &= ~(TOPIC97_AVS_AUDIO_CONTROL | TOPIC97_AVS_VIDEO_CONTROL); +		config_writeb(socket, TOPIC97_AUDIO_VIDEO_SWITCH, reg); +	}  }  static int topic97_override(struct yenta_socket *socket) diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index 1d8d9879d3a..48857008758 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c @@ -167,6 +167,8 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev)  		return -ENOMEM;  	} +	isink->wm831x = wm831x; +  	res = platform_get_resource(pdev, IORESOURCE_IO, 0);  	if (res == NULL) {  		dev_err(&pdev->dev, "No I/O resource\n"); diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c index 33a10c47260..4c5d5d0c4cf 100644 --- a/drivers/rtc/rtc-pcf50633.c +++ b/drivers/rtc/rtc-pcf50633.c @@ -292,8 +292,9 @@ static int __devinit pcf50633_rtc_probe(struct platform_device *pdev)  				&pcf50633_rtc_ops, THIS_MODULE);  	if (IS_ERR(rtc->rtc_dev)) { +		int ret =  PTR_ERR(rtc->rtc_dev);  		kfree(rtc); -		return PTR_ERR(rtc->rtc_dev); +		return ret;  	}  	pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM, diff --git a/drivers/rtc/rtc-x1205.c b/drivers/rtc/rtc-x1205.c index 310c10795e9..6583c1a8b07 100644 --- a/drivers/rtc/rtc-x1205.c +++ b/drivers/rtc/rtc-x1205.c @@ -195,7 +195,7 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,  		/* year, since the rtc epoch*/  		buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);  		buf[CCR_WDAY] = tm->tm_wday & 0x07; -		buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100); +		buf[CCR_Y2K] = bin2bcd((tm->tm_year + 1900) / 100);  	}  	/* If writing alarm registers, set compare bits on registers 0-4 */ @@ -280,9 +280,9 @@ static int x1205_fix_osc(struct i2c_client *client)  	int err;  	struct rtc_time tm; -	tm.tm_hour = tm.tm_min = tm.tm_sec = 0; +	memset(&tm, 0, sizeof(tm)); -	err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE, 0); +	err = x1205_set_datetime(client, &tm, 1, X1205_CCR_BASE, 0);  	if (err < 0)  		dev_err(&client->dev, "unable to restart the oscillator\n"); diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index 67cde013806..528733b4a39 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -54,15 +54,6 @@  #include <pcmcia/cistpl.h>  #include <pcmcia/ds.h> -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"aha152x_cs.c 1.54 2000/06/12 21:27:25 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -103,7 +94,7 @@ static int aha152x_probe(struct pcmcia_device *link)  {      scsi_info_t *info; -    DEBUG(0, "aha152x_attach()\n"); +    dev_dbg(&link->dev, "aha152x_attach()\n");      /* Create new SCSI device */      info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -115,7 +106,6 @@ static int aha152x_probe(struct pcmcia_device *link)      link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;      link->io.IOAddrLines = 10;      link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID;      link->conf.Attributes = CONF_ENABLE_IRQ;      link->conf.IntType = INT_MEMORY_AND_IO;      link->conf.Present = PRESENT_OPTION; @@ -127,7 +117,7 @@ static int aha152x_probe(struct pcmcia_device *link)  static void aha152x_detach(struct pcmcia_device *link)  { -    DEBUG(0, "aha152x_detach(0x%p)\n", link); +    dev_dbg(&link->dev, "aha152x_detach\n");      aha152x_release_cs(link); @@ -137,9 +127,6 @@ static void aha152x_detach(struct pcmcia_device *link)  /*====================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int aha152x_config_check(struct pcmcia_device *p_dev,  				cistpl_cftable_entry_t *cfg,  				cistpl_cftable_entry_t *dflt, @@ -164,19 +151,22 @@ static int aha152x_config_cs(struct pcmcia_device *link)  {      scsi_info_t *info = link->priv;      struct aha152x_setup s; -    int last_ret, last_fn; +    int ret;      struct Scsi_Host *host; -    DEBUG(0, "aha152x_config(0x%p)\n", link); +    dev_dbg(&link->dev, "aha152x_config\n"); -    last_ret = pcmcia_loop_config(link, aha152x_config_check, NULL); -    if (last_ret) { -	cs_error(link, RequestIO, last_ret); -	goto failed; -    } +    ret = pcmcia_loop_config(link, aha152x_config_check, NULL); +    if (ret) +	    goto failed; -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; + +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      /* Set configuration options for the aha152x driver */      memset(&s, 0, sizeof(s)); @@ -194,7 +184,7 @@ static int aha152x_config_cs(struct pcmcia_device *link)      host = aha152x_probe_one(&s);      if (host == NULL) {  	printk(KERN_INFO "aha152x_cs: no SCSI devices found\n"); -	goto cs_failed; +	goto failed;      }      sprintf(info->node.dev_name, "scsi%d", host->host_no); @@ -203,8 +193,6 @@ static int aha152x_config_cs(struct pcmcia_device *link)      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      aha152x_release_cs(link);      return -ENODEV; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 06254f46a0d..91404068407 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -59,16 +59,6 @@ MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");  MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver");  MODULE_LICENSE("Dual MPL/GPL"); -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif -  /*====================================================================*/  typedef struct scsi_info_t { @@ -86,7 +76,7 @@ static int fdomain_probe(struct pcmcia_device *link)  {  	scsi_info_t *info; -	DEBUG(0, "fdomain_attach()\n"); +	dev_dbg(&link->dev, "fdomain_attach()\n");  	/* Create new SCSI device */  	info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -99,7 +89,6 @@ static int fdomain_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;  	link->io.IOAddrLines = 10;  	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO;  	link->conf.Present = PRESENT_OPTION; @@ -111,7 +100,7 @@ static int fdomain_probe(struct pcmcia_device *link)  static void fdomain_detach(struct pcmcia_device *link)  { -	DEBUG(0, "fdomain_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "fdomain_detach\n");  	fdomain_release(link); @@ -120,9 +109,6 @@ static void fdomain_detach(struct pcmcia_device *link)  /*====================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int fdomain_config_check(struct pcmcia_device *p_dev,  				cistpl_cftable_entry_t *cfg,  				cistpl_cftable_entry_t *dflt, @@ -137,20 +123,22 @@ static int fdomain_config_check(struct pcmcia_device *p_dev,  static int fdomain_config(struct pcmcia_device *link)  {      scsi_info_t *info = link->priv; -    int last_ret, last_fn; +    int ret;      char str[22];      struct Scsi_Host *host; -    DEBUG(0, "fdomain_config(0x%p)\n", link); +    dev_dbg(&link->dev, "fdomain_config\n"); -    last_ret = pcmcia_loop_config(link, fdomain_config_check, NULL); -    if (last_ret) { -	    cs_error(link, RequestIO, last_ret); +    ret = pcmcia_loop_config(link, fdomain_config_check, NULL); +    if (ret)  	    goto failed; -    } -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed; +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      /* A bad hack... */      release_region(link->io.BasePort1, link->io.NumPorts1); @@ -162,11 +150,11 @@ static int fdomain_config(struct pcmcia_device *link)      host = __fdomain_16x0_detect(&fdomain_driver_template);      if (!host) {          printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); -	goto cs_failed; +	goto failed;      }      if (scsi_add_host(host, NULL)) -	    goto cs_failed; +	    goto failed;      scsi_scan_host(host);      sprintf(info->node.dev_name, "scsi%d", host->host_no); @@ -175,8 +163,6 @@ static int fdomain_config(struct pcmcia_device *link)      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      fdomain_release(link);      return -ENODEV; @@ -188,7 +174,7 @@ static void fdomain_release(struct pcmcia_device *link)  {  	scsi_info_t *info = link->priv; -	DEBUG(0, "fdomain_release(0x%p)\n", link); +	dev_dbg(&link->dev, "fdomain_release\n");  	scsi_remove_host(info->host);  	pcmcia_disable_device(link); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index e32c344d7ad..c2341af587a 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1564,12 +1564,10 @@ static int nsp_cs_probe(struct pcmcia_device *link)  	link->io.IOAddrLines	 = 10;	/* not used */  	/* Interrupt setup */ -	link->irq.Attributes	 = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1	 = IRQ_LEVEL_ID; +	link->irq.Attributes	 = IRQ_TYPE_EXCLUSIVE;  	/* Interrupt handler */  	link->irq.Handler	 = &nspintr; -	link->irq.Instance       = info;  	link->irq.Attributes     |= IRQF_SHARED;  	/* General socket configuration */ @@ -1684,10 +1682,10 @@ static int nsp_cs_config_check(struct pcmcia_device *p_dev,  			if (cfg_mem->req.Size < 0x1000)  				cfg_mem->req.Size = 0x1000;  			cfg_mem->req.AccessSpeed = 0; -			if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0) +			if (pcmcia_request_window(p_dev, &cfg_mem->req, &p_dev->win) != 0)  				goto next_entry;  			map.Page = 0; map.CardOffset = mem->win[0].card_addr; -			if (pcmcia_map_mem_page(p_dev->win, &map) != 0) +			if (pcmcia_map_mem_page(p_dev, p_dev->win, &map) != 0)  				goto next_entry;  			cfg_mem->data->MmioAddress = (unsigned long) ioremap_nocache(cfg_mem->req.Base, cfg_mem->req.Size); diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index 20c3e5e6d88..f85f094870b 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -62,15 +62,6 @@  static char qlogic_name[] = "qlogic_cs"; -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "qlogic_cs.c 1.79-ac 2002/10/26 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif -  static struct scsi_host_template qlogicfas_driver_template = {  	.module			= THIS_MODULE,  	.name			= qlogic_name, @@ -159,7 +150,7 @@ static int qlogic_probe(struct pcmcia_device *link)  {  	scsi_info_t *info; -	DEBUG(0, "qlogic_attach()\n"); +	dev_dbg(&link->dev, "qlogic_attach()\n");  	/* Create new SCSI device */  	info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -171,7 +162,6 @@ static int qlogic_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;  	link->io.IOAddrLines = 10;  	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO;  	link->conf.Present = PRESENT_OPTION; @@ -183,7 +173,7 @@ static int qlogic_probe(struct pcmcia_device *link)  static void qlogic_detach(struct pcmcia_device *link)  { -	DEBUG(0, "qlogic_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "qlogic_detach\n");  	qlogic_release(link);  	kfree(link->priv); @@ -192,9 +182,6 @@ static void qlogic_detach(struct pcmcia_device *link)  /*====================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int qlogic_config_check(struct pcmcia_device *p_dev,  			       cistpl_cftable_entry_t *cfg,  			       cistpl_cftable_entry_t *dflt, @@ -213,19 +200,22 @@ static int qlogic_config_check(struct pcmcia_device *p_dev,  static int qlogic_config(struct pcmcia_device * link)  {  	scsi_info_t *info = link->priv; -	int last_ret, last_fn; +	int ret;  	struct Scsi_Host *host; -	DEBUG(0, "qlogic_config(0x%p)\n", link); +	dev_dbg(&link->dev, "qlogic_config\n"); -	last_ret = pcmcia_loop_config(link, qlogic_config_check, NULL); -	if (last_ret) { -		cs_error(link, RequestIO, last_ret); +	ret = pcmcia_loop_config(link, qlogic_config_check, NULL); +	if (ret) +		goto failed; + +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret)  		goto failed; -	} -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	if ((info->manf_id == MANFID_MACNICA) || (info->manf_id == MANFID_PIONEER) || (info->manf_id == 0x0098)) {  		/* set ATAcmd */ @@ -244,7 +234,7 @@ static int qlogic_config(struct pcmcia_device * link)  	if (!host) {  		printk(KERN_INFO "%s: no SCSI devices found\n", qlogic_name); -		goto cs_failed; +		goto failed;  	}  	sprintf(info->node.dev_name, "scsi%d", host->host_no); @@ -253,12 +243,9 @@ static int qlogic_config(struct pcmcia_device * link)  	return 0; -cs_failed: -	cs_error(link, last_fn, last_ret); -	pcmcia_disable_device(link);  failed: +	pcmcia_disable_device(link);  	return -ENODEV; -  }				/* qlogic_config */  /*====================================================================*/ @@ -267,7 +254,7 @@ static void qlogic_release(struct pcmcia_device *link)  {  	scsi_info_t *info = link->priv; -	DEBUG(0, "qlogic_release(0x%p)\n", link); +	dev_dbg(&link->dev, "qlogic_release\n");  	scsi_remove_host(info->host); diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index b330c11a175..e7564d8f0cb 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -77,17 +77,6 @@  #include <pcmcia/ds.h>  #include <pcmcia/ciscode.h> -/* ================================================================== */ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"sym53c500_cs.c 0.9c 2004/10/27 (Bob Tracy)"; -#else -#define DEBUG(n, args...) -#endif  /* ================================================================== */ @@ -525,7 +514,7 @@ SYM53C500_release(struct pcmcia_device *link)  	struct scsi_info_t *info = link->priv;  	struct Scsi_Host *shost = info->host; -	DEBUG(0, "SYM53C500_release(0x%p)\n", link); +	dev_dbg(&link->dev, "SYM53C500_release\n");  	/*  	*  Do this before releasing/freeing resources. @@ -697,9 +686,6 @@ static struct scsi_host_template sym53c500_driver_template = {       .shost_attrs		= SYM53C500_shost_attrs  }; -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int SYM53C500_config_check(struct pcmcia_device *p_dev,  				  cistpl_cftable_entry_t *cfg,  				  cistpl_cftable_entry_t *dflt, @@ -719,24 +705,27 @@ static int  SYM53C500_config(struct pcmcia_device *link)  {  	struct scsi_info_t *info = link->priv; -	int last_ret, last_fn; +	int ret;  	int irq_level, port_base;  	struct Scsi_Host *host;  	struct scsi_host_template *tpnt = &sym53c500_driver_template;  	struct sym53c500_data *data; -	DEBUG(0, "SYM53C500_config(0x%p)\n", link); +	dev_dbg(&link->dev, "SYM53C500_config\n");  	info->manf_id = link->manf_id; -	last_ret = pcmcia_loop_config(link, SYM53C500_config_check, NULL); -	if (last_ret) { -		cs_error(link, RequestIO, last_ret); +	ret = pcmcia_loop_config(link, SYM53C500_config_check, NULL); +	if (ret) +		goto failed; + +	ret = pcmcia_request_irq(link, &link->irq); +	if (ret)  		goto failed; -	} -	CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); -	CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/*  	*  That's the trouble with copying liberally from another driver. @@ -824,8 +813,6 @@ err_release:  	printk(KERN_INFO "sym53c500_cs: no SCSI devices found\n");  	return -ENODEV; -cs_failed: -	cs_error(link, last_fn, last_ret);  failed:  	SYM53C500_release(link);  	return -ENODEV; @@ -855,7 +842,7 @@ static int sym53c500_resume(struct pcmcia_device *link)  static void  SYM53C500_detach(struct pcmcia_device *link)  { -	DEBUG(0, "SYM53C500_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "SYM53C500_detach\n");  	SYM53C500_release(link); @@ -868,7 +855,7 @@ SYM53C500_probe(struct pcmcia_device *link)  {  	struct scsi_info_t *info; -	DEBUG(0, "SYM53C500_attach()\n"); +	dev_dbg(&link->dev, "SYM53C500_attach()\n");  	/* Create new SCSI device */  	info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -880,7 +867,6 @@ SYM53C500_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;  	link->io.IOAddrLines = 10;  	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 7c7914f5fa0..fc413f0f8dd 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -54,14 +54,6 @@  #include "8250.h" -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -121,24 +113,20 @@ static void quirk_setup_brainboxes_0104(struct pcmcia_device *link, struct uart_  static int quirk_post_ibm(struct pcmcia_device *link)  {  	conf_reg_t reg = { 0, CS_READ, 0x800, 0 }; -	int last_ret, last_fn; +	int ret; + +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed; -	last_ret = pcmcia_access_configuration_register(link, ®); -	if (last_ret) { -		last_fn = AccessConfigurationRegister; -		goto cs_failed; -	}  	reg.Action = CS_WRITE;  	reg.Value = reg.Value | 1; -	last_ret = pcmcia_access_configuration_register(link, ®); -	if (last_ret) { -		last_fn = AccessConfigurationRegister; -		goto cs_failed; -	} +	ret = pcmcia_access_configuration_register(link, ®); +	if (ret) +		goto failed;  	return 0; - cs_failed: -	cs_error(link, last_fn, last_ret); + failed:  	return -ENODEV;  } @@ -283,7 +271,7 @@ static void serial_remove(struct pcmcia_device *link)  	struct serial_info *info = link->priv;  	int i; -	DEBUG(0, "serial_release(0x%p)\n", link); +	dev_dbg(&link->dev, "serial_release\n");  	/*  	 * Recheck to see if the device is still configured. @@ -334,7 +322,7 @@ static int serial_probe(struct pcmcia_device *link)  {  	struct serial_info *info; -	DEBUG(0, "serial_attach()\n"); +	dev_dbg(&link->dev, "serial_attach()\n");  	/* Create new serial device */  	info = kzalloc(sizeof (*info), GFP_KERNEL); @@ -346,7 +334,6 @@ static int serial_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;  	link->io.NumPorts1 = 8;  	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	if (do_sound) {  		link->conf.Attributes |= CONF_ENABLE_SPKR; @@ -370,7 +357,7 @@ static void serial_detach(struct pcmcia_device *link)  {  	struct serial_info *info = link->priv; -	DEBUG(0, "serial_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "serial_detach\n");  	/*  	 * Ensure any outstanding scheduled tasks are completed. @@ -399,7 +386,7 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,  	port.irq = irq;  	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ;  	port.uartclk = 1843200; -	port.dev = &handle_to_dev(handle); +	port.dev = &handle->dev;  	if (buggy_uart)  		port.flags |= UPF_BUGGY_UART; @@ -426,21 +413,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,  /*====================================================================*/ -static int -first_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse) -{ -	int i; -	i = pcmcia_get_first_tuple(handle, tuple); -	if (i != 0) -		return i; -	i = pcmcia_get_tuple_data(handle, tuple); -	if (i != 0) -		return i; -	return pcmcia_parse_tuple(tuple, parse); -} - -/*====================================================================*/ -  static int simple_config_check(struct pcmcia_device *p_dev,  			       cistpl_cftable_entry_t *cf,  			       cistpl_cftable_entry_t *dflt, @@ -522,15 +494,13 @@ static int simple_config(struct pcmcia_device *link)  	printk(KERN_NOTICE  	       "serial_cs: no usable port range found, giving up\n"); -	cs_error(link, RequestIO, i);  	return -1;  found_port:  	i = pcmcia_request_irq(link, &link->irq); -	if (i != 0) { -		cs_error(link, RequestIRQ, i); +	if (i != 0)  		link->irq.AssignedIRQ = 0; -	} +  	if (info->multi && (info->manfid == MANFID_3COM))  		link->conf.ConfigIndex &= ~(0x08); @@ -541,10 +511,8 @@ found_port:  		info->quirk->config(link);  	i = pcmcia_request_configuration(link, &link->conf); -	if (i != 0) { -		cs_error(link, RequestConfiguration, i); +	if (i != 0)  		return -1; -	}  	return setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);  } @@ -613,7 +581,6 @@ static int multi_config(struct pcmcia_device *link)  		/* FIXME: comment does not fit, error handling does not fit */  		printk(KERN_NOTICE  		       "serial_cs: no usable port range found, giving up\n"); -		cs_error(link, RequestIRQ, i);  		link->irq.AssignedIRQ = 0;  	} @@ -624,10 +591,8 @@ static int multi_config(struct pcmcia_device *link)  		info->quirk->config(link);  	i = pcmcia_request_configuration(link, &link->conf); -	if (i != 0) { -		cs_error(link, RequestConfiguration, i); +	if (i != 0)  		return -ENODEV; -	}  	/* The Oxford Semiconductor OXCF950 cards are in fact single-port:  	 * 8 registers are for the UART, the others are extra registers. @@ -665,6 +630,25 @@ static int multi_config(struct pcmcia_device *link)  	return 0;  } +static int serial_check_for_multi(struct pcmcia_device *p_dev, +				  cistpl_cftable_entry_t *cf, +				  cistpl_cftable_entry_t *dflt, +				  unsigned int vcc, +				  void *priv_data) +{ +	struct serial_info *info = p_dev->priv; + +	if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) +		info->multi = cf->io.win[0].len >> 3; + +	if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && +		(cf->io.win[1].len == 8)) +		info->multi = 2; + +	return 0; /* break */ +} + +  /*======================================================================      serial_config() is scheduled to run after a CARD_INSERTION event @@ -676,46 +660,14 @@ static int multi_config(struct pcmcia_device *link)  static int serial_config(struct pcmcia_device * link)  {  	struct serial_info *info = link->priv; -	struct serial_cfg_mem *cfg_mem; -	tuple_t *tuple; -	u_char *buf; -	cisparse_t *parse; -	cistpl_cftable_entry_t *cf; -	int i, last_ret, last_fn; - -	DEBUG(0, "serial_config(0x%p)\n", link); - -	cfg_mem = kmalloc(sizeof(struct serial_cfg_mem), GFP_KERNEL); -	if (!cfg_mem) -		goto failed; - -	tuple = &cfg_mem->tuple; -	parse = &cfg_mem->parse; -	cf = &parse->cftable_entry; -	buf = cfg_mem->buf; - -	tuple->TupleData = (cisdata_t *) buf; -	tuple->TupleOffset = 0; -	tuple->TupleDataMax = 255; -	tuple->Attributes = 0; +	int i; -	/* Get configuration register information */ -	tuple->DesiredTuple = CISTPL_CONFIG; -	last_ret = first_tuple(link, tuple, parse); -	if (last_ret != 0) { -		last_fn = ParseTuple; -		goto cs_failed; -	} -	link->conf.ConfigBase = parse->config.base; -	link->conf.Present = parse->config.rmask[0]; +	dev_dbg(&link->dev, "serial_config\n");  	/* Is this a compliant multifunction card? */ -	tuple->DesiredTuple = CISTPL_LONGLINK_MFC; -	tuple->Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; -	info->multi = (first_tuple(link, tuple, parse) == 0); +	info->multi = (link->socket->functions > 1);  	/* Is this a multiport card? */ -	tuple->DesiredTuple = CISTPL_MANFID;  	info->manfid = link->manf_id;  	info->prodid = link->card_id; @@ -730,20 +682,11 @@ static int serial_config(struct pcmcia_device * link)  	/* Another check for dual-serial cards: look for either serial or  	   multifunction cards that ask for appropriate IO port ranges */ -	tuple->DesiredTuple = CISTPL_FUNCID;  	if ((info->multi == 0) &&  	    (link->has_func_id) &&  	    ((link->func_id == CISTPL_FUNCID_MULTI) || -	     (link->func_id == CISTPL_FUNCID_SERIAL))) { -		tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY; -		if (first_tuple(link, tuple, parse) == 0) { -			if ((cf->io.nwin == 1) && (cf->io.win[0].len % 8 == 0)) -				info->multi = cf->io.win[0].len >> 3; -			if ((cf->io.nwin == 2) && (cf->io.win[0].len == 8) && -			    (cf->io.win[1].len == 8)) -				info->multi = 2; -		} -	} +	     (link->func_id == CISTPL_FUNCID_SERIAL))) +		pcmcia_loop_config(link, serial_check_for_multi, info);  	/*  	 * Apply any multi-port quirk. @@ -768,14 +711,10 @@ static int serial_config(struct pcmcia_device * link)  			goto failed;  	link->dev_node = &info->node[0]; -	kfree(cfg_mem);  	return 0; -cs_failed: -	cs_error(link, last_fn, last_ret);  failed:  	serial_remove(link); -	kfree(cfg_mem);  	return -ENODEV;  } diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c index 96057de133a..19f75627c3d 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -29,6 +29,8 @@  #define SPI_FIFO_SIZE 4 +#define SPI_MAX_DIVIDER 0xff	/* Max. value for SPCR1.SER */ +#define SPI_MIN_DIVIDER 1	/* Min. value for SPCR1.SER */  #define TXx9_SPMCR		0x00  #define TXx9_SPCR0		0x04 @@ -193,11 +195,8 @@ static void txx9spi_work_one(struct txx9spi *c, struct spi_message *m)  		if (prev_speed_hz != speed_hz  				|| prev_bits_per_word != bits_per_word) { -			u32 n = (c->baseclk + speed_hz - 1) / speed_hz; -			if (n < 1) -				n = 1; -			else if (n > 0xff) -				n = 0xff; +			int n = DIV_ROUND_UP(c->baseclk, speed_hz) - 1; +			n = clamp(n, SPI_MIN_DIVIDER, SPI_MAX_DIVIDER);  			/* enter config mode */  			txx9spi_wr(c, mcr | TXx9_SPMCR_CONFIG | TXx9_SPMCR_BCLR,  					TXx9_SPMCR); @@ -370,8 +369,8 @@ static int __init txx9spi_probe(struct platform_device *dev)  		goto exit;  	}  	c->baseclk = clk_get_rate(c->clk); -	c->min_speed_hz = (c->baseclk + 0xff - 1) / 0xff; -	c->max_speed_hz = c->baseclk; +	c->min_speed_hz = DIV_ROUND_UP(c->baseclk, SPI_MAX_DIVIDER + 1); +	c->max_speed_hz = c->baseclk / (SPI_MIN_DIVIDER + 1);  	res = platform_get_resource(dev, IORESOURCE_MEM, 0);  	if (!res) diff --git a/drivers/ssb/pcmcia.c b/drivers/ssb/pcmcia.c index 100e7a5c5ea..e72f4046a5e 100644 --- a/drivers/ssb/pcmcia.c +++ b/drivers/ssb/pcmcia.c @@ -617,136 +617,140 @@ static int ssb_pcmcia_sprom_check_crc(const u16 *sprom, size_t size)  	}						\    } while (0) -int ssb_pcmcia_get_invariants(struct ssb_bus *bus, -			      struct ssb_init_invariants *iv) +static int ssb_pcmcia_get_mac(struct pcmcia_device *p_dev, +			tuple_t *tuple, +			void *priv)  { -	tuple_t tuple; -	int res; -	unsigned char buf[32]; +	struct ssb_sprom *sprom = priv; + +	if (tuple->TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID) +		return -EINVAL; +	if (tuple->TupleDataLen != ETH_ALEN + 2) +		return -EINVAL; +	if (tuple->TupleData[1] != ETH_ALEN) +		return -EINVAL; +	memcpy(sprom->il0mac, &tuple->TupleData[2], ETH_ALEN); +	return 0; +}; + +static int ssb_pcmcia_do_get_invariants(struct pcmcia_device *p_dev, +					tuple_t *tuple, +					void *priv) +{ +	struct ssb_init_invariants *iv = priv;  	struct ssb_sprom *sprom = &iv->sprom;  	struct ssb_boardinfo *bi = &iv->boardinfo;  	const char *error_description; +	GOTO_ERROR_ON(tuple->TupleDataLen < 1, "VEN tpl < 1"); +	switch (tuple->TupleData[0]) { +	case SSB_PCMCIA_CIS_ID: +		GOTO_ERROR_ON((tuple->TupleDataLen != 5) && +			      (tuple->TupleDataLen != 7), +			      "id tpl size"); +		bi->vendor = tuple->TupleData[1] | +			((u16)tuple->TupleData[2] << 8); +		break; +	case SSB_PCMCIA_CIS_BOARDREV: +		GOTO_ERROR_ON(tuple->TupleDataLen != 2, +			"boardrev tpl size"); +		sprom->board_rev = tuple->TupleData[1]; +		break; +	case SSB_PCMCIA_CIS_PA: +		GOTO_ERROR_ON((tuple->TupleDataLen != 9) && +			(tuple->TupleDataLen != 10), +			"pa tpl size"); +		sprom->pa0b0 = tuple->TupleData[1] | +			((u16)tuple->TupleData[2] << 8); +		sprom->pa0b1 = tuple->TupleData[3] | +			((u16)tuple->TupleData[4] << 8); +		sprom->pa0b2 = tuple->TupleData[5] | +			((u16)tuple->TupleData[6] << 8); +		sprom->itssi_a = tuple->TupleData[7]; +		sprom->itssi_bg = tuple->TupleData[7]; +		sprom->maxpwr_a = tuple->TupleData[8]; +		sprom->maxpwr_bg = tuple->TupleData[8]; +		break; +	case SSB_PCMCIA_CIS_OEMNAME: +		/* We ignore this. */ +		break; +	case SSB_PCMCIA_CIS_CCODE: +		GOTO_ERROR_ON(tuple->TupleDataLen != 2, +			"ccode tpl size"); +		sprom->country_code = tuple->TupleData[1]; +		break; +	case SSB_PCMCIA_CIS_ANTENNA: +		GOTO_ERROR_ON(tuple->TupleDataLen != 2, +			"ant tpl size"); +		sprom->ant_available_a = tuple->TupleData[1]; +		sprom->ant_available_bg = tuple->TupleData[1]; +		break; +	case SSB_PCMCIA_CIS_ANTGAIN: +		GOTO_ERROR_ON(tuple->TupleDataLen != 2, +			"antg tpl size"); +		sprom->antenna_gain.ghz24.a0 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz24.a1 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz24.a2 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz24.a3 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz5.a0 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz5.a1 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz5.a2 = tuple->TupleData[1]; +		sprom->antenna_gain.ghz5.a3 = tuple->TupleData[1]; +		break; +	case SSB_PCMCIA_CIS_BFLAGS: +		GOTO_ERROR_ON((tuple->TupleDataLen != 3) && +			(tuple->TupleDataLen != 5), +			"bfl tpl size"); +		sprom->boardflags_lo = tuple->TupleData[1] | +			((u16)tuple->TupleData[2] << 8); +		break; +	case SSB_PCMCIA_CIS_LEDS: +		GOTO_ERROR_ON(tuple->TupleDataLen != 5, +			"leds tpl size"); +		sprom->gpio0 = tuple->TupleData[1]; +		sprom->gpio1 = tuple->TupleData[2]; +		sprom->gpio2 = tuple->TupleData[3]; +		sprom->gpio3 = tuple->TupleData[4]; +		break; +	} +	return -ENOSPC; /* continue with next entry */ + +error: +	ssb_printk(KERN_ERR PFX +		   "PCMCIA: Failed to fetch device invariants: %s\n", +		   error_description); +	return -ENODEV; +} + + +int ssb_pcmcia_get_invariants(struct ssb_bus *bus, +			      struct ssb_init_invariants *iv) +{ +	struct ssb_sprom *sprom = &iv->sprom; +	int res; +  	memset(sprom, 0xFF, sizeof(*sprom));  	sprom->revision = 1;  	sprom->boardflags_lo = 0;  	sprom->boardflags_hi = 0;  	/* First fetch the MAC address. */ -	memset(&tuple, 0, sizeof(tuple)); -	tuple.DesiredTuple = CISTPL_FUNCE; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple); -	GOTO_ERROR_ON(res != 0, "MAC first tpl"); -	res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); -	GOTO_ERROR_ON(res != 0, "MAC first tpl data"); -	while (1) { -		GOTO_ERROR_ON(tuple.TupleDataLen < 1, "MAC tpl < 1"); -		if (tuple.TupleData[0] == CISTPL_FUNCE_LAN_NODE_ID) -			break; -		res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple); -		GOTO_ERROR_ON(res != 0, "MAC next tpl"); -		res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); -		GOTO_ERROR_ON(res != 0, "MAC next tpl data"); +	res = pcmcia_loop_tuple(bus->host_pcmcia, CISTPL_FUNCE, +				ssb_pcmcia_get_mac, sprom); +	if (res != 0) { +		ssb_printk(KERN_ERR PFX +			"PCMCIA: Failed to fetch MAC address\n"); +		return -ENODEV;  	} -	GOTO_ERROR_ON(tuple.TupleDataLen != ETH_ALEN + 2, "MAC tpl size"); -	memcpy(sprom->il0mac, &tuple.TupleData[2], ETH_ALEN);  	/* Fetch the vendor specific tuples. */ -	memset(&tuple, 0, sizeof(tuple)); -	tuple.DesiredTuple = SSB_PCMCIA_CIS; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	res = pcmcia_get_first_tuple(bus->host_pcmcia, &tuple); -	GOTO_ERROR_ON(res != 0, "VEN first tpl"); -	res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); -	GOTO_ERROR_ON(res != 0, "VEN first tpl data"); -	while (1) { -		GOTO_ERROR_ON(tuple.TupleDataLen < 1, "VEN tpl < 1"); -		switch (tuple.TupleData[0]) { -		case SSB_PCMCIA_CIS_ID: -			GOTO_ERROR_ON((tuple.TupleDataLen != 5) && -				      (tuple.TupleDataLen != 7), -				      "id tpl size"); -			bi->vendor = tuple.TupleData[1] | -			       ((u16)tuple.TupleData[2] << 8); -			break; -		case SSB_PCMCIA_CIS_BOARDREV: -			GOTO_ERROR_ON(tuple.TupleDataLen != 2, -				      "boardrev tpl size"); -			sprom->board_rev = tuple.TupleData[1]; -			break; -		case SSB_PCMCIA_CIS_PA: -			GOTO_ERROR_ON((tuple.TupleDataLen != 9) && -				      (tuple.TupleDataLen != 10), -				      "pa tpl size"); -			sprom->pa0b0 = tuple.TupleData[1] | -				 ((u16)tuple.TupleData[2] << 8); -			sprom->pa0b1 = tuple.TupleData[3] | -				 ((u16)tuple.TupleData[4] << 8); -			sprom->pa0b2 = tuple.TupleData[5] | -				 ((u16)tuple.TupleData[6] << 8); -			sprom->itssi_a = tuple.TupleData[7]; -			sprom->itssi_bg = tuple.TupleData[7]; -			sprom->maxpwr_a = tuple.TupleData[8]; -			sprom->maxpwr_bg = tuple.TupleData[8]; -			break; -		case SSB_PCMCIA_CIS_OEMNAME: -			/* We ignore this. */ -			break; -		case SSB_PCMCIA_CIS_CCODE: -			GOTO_ERROR_ON(tuple.TupleDataLen != 2, -				      "ccode tpl size"); -			sprom->country_code = tuple.TupleData[1]; -			break; -		case SSB_PCMCIA_CIS_ANTENNA: -			GOTO_ERROR_ON(tuple.TupleDataLen != 2, -				      "ant tpl size"); -			sprom->ant_available_a = tuple.TupleData[1]; -			sprom->ant_available_bg = tuple.TupleData[1]; -			break; -		case SSB_PCMCIA_CIS_ANTGAIN: -			GOTO_ERROR_ON(tuple.TupleDataLen != 2, -				      "antg tpl size"); -			sprom->antenna_gain.ghz24.a0 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz24.a1 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz24.a2 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz24.a3 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz5.a0 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz5.a1 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz5.a2 = tuple.TupleData[1]; -			sprom->antenna_gain.ghz5.a3 = tuple.TupleData[1]; -			break; -		case SSB_PCMCIA_CIS_BFLAGS: -			GOTO_ERROR_ON((tuple.TupleDataLen != 3) && -				      (tuple.TupleDataLen != 5), -				      "bfl tpl size"); -			sprom->boardflags_lo = tuple.TupleData[1] | -					 ((u16)tuple.TupleData[2] << 8); -			break; -		case SSB_PCMCIA_CIS_LEDS: -			GOTO_ERROR_ON(tuple.TupleDataLen != 5, -				      "leds tpl size"); -			sprom->gpio0 = tuple.TupleData[1]; -			sprom->gpio1 = tuple.TupleData[2]; -			sprom->gpio2 = tuple.TupleData[3]; -			sprom->gpio3 = tuple.TupleData[4]; -			break; -		} -		res = pcmcia_get_next_tuple(bus->host_pcmcia, &tuple); -		if (res == -ENOSPC) -			break; -		GOTO_ERROR_ON(res != 0, "VEN next tpl"); -		res = pcmcia_get_tuple_data(bus->host_pcmcia, &tuple); -		GOTO_ERROR_ON(res != 0, "VEN next tpl data"); -	} +	res = pcmcia_loop_tuple(bus->host_pcmcia, SSB_PCMCIA_CIS, +				ssb_pcmcia_do_get_invariants, sprom); +	if ((res == 0) || (res == -ENOSPC)) +		return 0; -	return 0; -error:  	ssb_printk(KERN_ERR PFX -		   "PCMCIA: Failed to fetch device invariants: %s\n", -		   error_description); +			"PCMCIA: Failed to fetch device invariants\n");  	return -ENODEV;  } diff --git a/drivers/staging/comedi/drivers/cb_das16_cs.c b/drivers/staging/comedi/drivers/cb_das16_cs.c index 80c0df8656f..39923cb388b 100644 --- a/drivers/staging/comedi/drivers/cb_das16_cs.c +++ b/drivers/staging/comedi/drivers/cb_das16_cs.c @@ -141,37 +141,14 @@ static int das16cs_timer_insn_config(struct comedi_device *dev,  				     struct comedi_insn *insn,  				     unsigned int *data); -static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link) -{ -	tuple_t tuple; -	u_short buf[128]; -	int prodid = 0; - -	tuple.TupleData = (cisdata_t *) buf; -	tuple.TupleOffset = 0; -	tuple.TupleDataMax = 255; -	tuple.DesiredTuple = CISTPL_MANFID; -	tuple.Attributes = TUPLE_RETURN_COMMON; -	if ((pcmcia_get_first_tuple(link, &tuple) == 0) && -	    (pcmcia_get_tuple_data(link, &tuple) == 0)) { -		prodid = le16_to_cpu(buf[1]); -	} - -	return prodid; -} -  static const struct das16cs_board *das16cs_probe(struct comedi_device *dev,  						 struct pcmcia_device *link)  { -	int id;  	int i; -	id = get_prodid(dev, link); -  	for (i = 0; i < n_boards; i++) { -		if (das16cs_boards[i].device_id == id) { +		if (das16cs_boards[i].device_id == link->card_id)  			return das16cs_boards + i; -		}  	}  	printk("unknown board!\n"); @@ -660,27 +637,8 @@ static int das16cs_timer_insn_config(struct comedi_device *dev,  ======================================================================*/ -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/  #if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE) -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -    "cb_das16_cs.c pcmcia code (David Schleef), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ -  static void das16cs_pcmcia_config(struct pcmcia_device *link);  static void das16cs_pcmcia_release(struct pcmcia_device *link);  static int das16cs_pcmcia_suspend(struct pcmcia_device *p_dev); @@ -733,7 +691,7 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)  {  	struct local_info_t *local; -	DEBUG(0, "das16cs_pcmcia_attach()\n"); +	dev_dbg(&link->dev, "das16cs_pcmcia_attach()\n");  	/* Allocate space for private device-specific data */  	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); @@ -745,7 +703,6 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)  	/* Initialize the pcmcia_device structure */  	/* Interrupt setup */  	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->irq.Handler = NULL;  	link->conf.Attributes = 0; @@ -760,7 +717,7 @@ static int das16cs_pcmcia_attach(struct pcmcia_device *link)  static void das16cs_pcmcia_detach(struct pcmcia_device *link)  { -	DEBUG(0, "das16cs_pcmcia_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "das16cs_pcmcia_detach\n");  	if (link->dev_node) {  		((struct local_info_t *)link->priv)->stop = 1; @@ -771,118 +728,55 @@ static void das16cs_pcmcia_detach(struct pcmcia_device *link)  		kfree(link->priv);  }				/* das16cs_pcmcia_detach */ -static void das16cs_pcmcia_config(struct pcmcia_device *link) -{ -	struct local_info_t *dev = link->priv; -	tuple_t tuple; -	cisparse_t parse; -	int last_fn, last_ret; -	u_char buf[64]; -	cistpl_cftable_entry_t dflt = { 0 }; - -	DEBUG(0, "das16cs_pcmcia_config(0x%p)\n", link); - -	/* -	   This reads the card's CONFIG tuple to find its configuration -	   registers. -	 */ -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	last_fn = GetFirstTuple; -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret != 0) -		goto cs_failed; -	last_fn = GetTupleData; -	last_ret = pcmcia_get_tuple_data(link, &tuple); -	if (last_ret != 0) -		goto cs_failed; - -	last_fn = ParseTuple; -	last_ret = pcmcia_parse_tuple(&tuple, &parse); -	if (last_ret != 0) -		goto cs_failed; - -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; - -	/* -	   In this loop, we scan the CIS for configuration table entries, -	   each of which describes a valid card configuration, including -	   voltage, IO window, memory window, and interrupt settings. - -	   We make no assumptions about the card to be configured: we use -	   just the information available in the CIS.  In an ideal world, -	   this would work for any PCMCIA card, but it requires a complete -	   and accurate CIS.  In practice, a driver usually "knows" most of -	   these things without consulting the CIS, and most client drivers -	   will only use the CIS to fill in implementation-defined details. -	 */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	last_fn = GetFirstTuple; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) -		goto cs_failed; - -	while (1) { -		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -		if (pcmcia_get_tuple_data(link, &tuple)) -			goto next_entry; -		if (pcmcia_parse_tuple(&tuple, &parse)) -			goto next_entry; +static int das16cs_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data) +{ +	if (cfg->index == 0) +		return -EINVAL; -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; -		/* Does this card need audio output? */ -/*	if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -		link->conf.Attributes |= CONF_ENABLE_SPKR; -		link->conf.Status = CCSR_AUDIO_ENA; +	/* IO window settings */ +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		} +		/* This reserves IO space but doesn't actually enable it */ +		return pcmcia_request_io(p_dev, &p_dev->io);  	} -*/ -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; -		/* IO window settings */ -		link->io.NumPorts1 = link->io.NumPorts2 = 0; -		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -			if (!(io->flags & CISTPL_IO_8BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -			if (!(io->flags & CISTPL_IO_16BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			link->io.NumPorts1 = io->win[0].len; -			if (io->nwin > 1) { -				link->io.Attributes2 = link->io.Attributes1; -				link->io.BasePort2 = io->win[1].base; -				link->io.NumPorts2 = io->win[1].len; -			} -			/* This reserves IO space but doesn't actually enable it */ -			if (pcmcia_request_io(link, &link->io)) -				goto next_entry; -		} +	return 0; +} -		/* If we got this far, we're cool! */ -		break; +static void das16cs_pcmcia_config(struct pcmcia_device *link) +{ +	struct local_info_t *dev = link->priv; +	int ret; -next_entry: -		last_fn = GetNextTuple; +	dev_dbg(&link->dev, "das16cs_pcmcia_config\n"); -		last_ret = pcmcia_get_next_tuple(link, &tuple); -		if (last_ret) -			goto cs_failed; +	ret = pcmcia_loop_config(link, das16cs_pcmcia_config_loop, NULL); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		goto failed;  	}  	/* @@ -891,21 +785,18 @@ next_entry:  	   irq structure is initialized.  	 */  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		last_fn = RequestIRQ; - -		last_ret = pcmcia_request_irq(link, &link->irq); -		if (last_ret) -			goto cs_failed; +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/*  	   This actually configures the PCMCIA socket -- setting up  	   the I/O windows and the interrupt mapping, and putting the  	   card and host interface into "Memory and IO" mode.  	 */ -	last_fn = RequestConfiguration; -	last_ret = pcmcia_request_configuration(link, &link->conf); -	if (last_ret) -		goto cs_failed; +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/*  	   At this point, the dev_node_t structure(s) need to be @@ -930,14 +821,13 @@ next_entry:  	return; -cs_failed: -	cs_error(link, last_fn, last_ret); +failed:  	das16cs_pcmcia_release(link);  }				/* das16cs_pcmcia_config */  static void das16cs_pcmcia_release(struct pcmcia_device *link)  { -	DEBUG(0, "das16cs_pcmcia_release(0x%p)\n", link); +	dev_dbg(&link->dev, "das16cs_pcmcia_release\n");  	pcmcia_disable_device(link);  }				/* das16cs_pcmcia_release */ @@ -983,14 +873,13 @@ struct pcmcia_driver das16cs_driver = {  static int __init init_das16cs_pcmcia_cs(void)  { -	DEBUG(0, "%s\n", version);  	pcmcia_register_driver(&das16cs_driver);  	return 0;  }  static void __exit exit_das16cs_pcmcia_cs(void)  { -	DEBUG(0, "das16cs_pcmcia_cs: unloading\n"); +	pr_debug("das16cs_pcmcia_cs: unloading\n");  	pcmcia_unregister_driver(&das16cs_driver);  } diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c index 9cab21eaaa1..9b945e5fdd3 100644 --- a/drivers/staging/comedi/drivers/das08_cs.c +++ b/drivers/staging/comedi/drivers/das08_cs.c @@ -110,25 +110,6 @@ static int das08_cs_attach(struct comedi_device *dev,  ======================================================================*/ -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static const char *version = -    "das08.c pcmcia code (Frank Hess), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/  static void das08_pcmcia_config(struct pcmcia_device *link);  static void das08_pcmcia_release(struct pcmcia_device *link);  static int das08_pcmcia_suspend(struct pcmcia_device *p_dev); @@ -181,7 +162,7 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)  {  	struct local_info_t *local; -	DEBUG(0, "das08_pcmcia_attach()\n"); +	dev_dbg(&link->dev, "das08_pcmcia_attach()\n");  	/* Allocate space for private device-specific data */  	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); @@ -192,7 +173,6 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)  	/* Interrupt setup */  	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->irq.Handler = NULL;  	/* @@ -224,7 +204,7 @@ static int das08_pcmcia_attach(struct pcmcia_device *link)  static void das08_pcmcia_detach(struct pcmcia_device *link)  { -	DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "das08_pcmcia_detach\n");  	if (link->dev_node) {  		((struct local_info_t *)link->priv)->stop = 1; @@ -237,6 +217,44 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)  }				/* das08_pcmcia_detach */ + +static int das08_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data) +{ +	if (cfg->index == 0) +		return -ENODEV; + +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; + +	/* IO window settings */ +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		} +		/* This reserves IO space but doesn't actually enable it */ +		return pcmcia_request_io(p_dev, &p_dev->io); +	} +	return 0; +} + +  /*======================================================================      das08_pcmcia_config() is scheduled to run after a CARD_INSERTION event @@ -248,128 +266,20 @@ static void das08_pcmcia_detach(struct pcmcia_device *link)  static void das08_pcmcia_config(struct pcmcia_device *link)  {  	struct local_info_t *dev = link->priv; -	tuple_t tuple; -	cisparse_t parse; -	int last_fn, last_ret; -	u_char buf[64]; -	cistpl_cftable_entry_t dflt = { 0 }; - -	DEBUG(0, "das08_pcmcia_config(0x%p)\n", link); - -	/* -	   This reads the card's CONFIG tuple to find its configuration -	   registers. -	 */ -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; -	last_fn = GetFirstTuple; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) -		goto cs_failed; - -	last_fn = GetTupleData; - -	last_ret = pcmcia_get_tuple_data(link, &tuple); -	if (last_ret) -		goto cs_failed; - -	last_fn = ParseTuple; - -	last_ret = pcmcia_parse_tuple(&tuple, &parse); -	if (last_ret) -		goto cs_failed; - -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; - -	/* -	   In this loop, we scan the CIS for configuration table entries, -	   each of which describes a valid card configuration, including -	   voltage, IO window, memory window, and interrupt settings. - -	   We make no assumptions about the card to be configured: we use -	   just the information available in the CIS.  In an ideal world, -	   this would work for any PCMCIA card, but it requires a complete -	   and accurate CIS.  In practice, a driver usually "knows" most of -	   these things without consulting the CIS, and most client drivers -	   will only use the CIS to fill in implementation-defined details. -	 */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	last_fn = GetFirstTuple; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) -		goto cs_failed; - -	while (1) { -		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - -		last_ret = pcmcia_get_tuple_data(link, &tuple); -		if (last_ret) -			goto next_entry; - -		last_ret = pcmcia_parse_tuple(&tuple, &parse); -		if (last_ret) -			goto next_entry; - -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; - -		/* Does this card need audio output? */ -/*	if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -		link->conf.Attributes |= CONF_ENABLE_SPKR; -		link->conf.Status = CCSR_AUDIO_ENA; -	} -*/ -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; - -		/* IO window settings */ -		link->io.NumPorts1 = link->io.NumPorts2 = 0; -		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -			if (!(io->flags & CISTPL_IO_8BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -			if (!(io->flags & CISTPL_IO_16BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			link->io.NumPorts1 = io->win[0].len; -			if (io->nwin > 1) { -				link->io.Attributes2 = link->io.Attributes1; -				link->io.BasePort2 = io->win[1].base; -				link->io.NumPorts2 = io->win[1].len; -			} -			/* This reserves IO space but doesn't actually enable it */ -			if (pcmcia_request_io(link, &link->io) != 0) -				goto next_entry; -		} - -		/* If we got this far, we're cool! */ -		break; +	int ret; -next_entry: -		last_fn = GetNextTuple; +	dev_dbg(&link->dev, "das08_pcmcia_config\n"); -		last_ret = pcmcia_get_next_tuple(link, &tuple); -		if (last_ret) -			goto cs_failed; +	ret = pcmcia_loop_config(link, das08_pcmcia_config_loop, NULL); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		goto failed;  	}  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		last_fn = RequestIRQ; -		last_ret = pcmcia_request_irq(link, &link->irq); -		if (last_ret) -			goto cs_failed; +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/* @@ -377,10 +287,9 @@ next_entry:  	   the I/O windows and the interrupt mapping, and putting the  	   card and host interface into "Memory and IO" mode.  	 */ -	last_fn = RequestConfiguration; -	last_ret = pcmcia_request_configuration(link, &link->conf); -	if (last_ret) -		goto cs_failed; +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/*  	   At this point, the dev_node_t structure(s) need to be @@ -405,8 +314,7 @@ next_entry:  	return; -cs_failed: -	cs_error(link, last_fn, last_ret); +failed:  	das08_pcmcia_release(link);  }				/* das08_pcmcia_config */ @@ -421,7 +329,7 @@ cs_failed:  static void das08_pcmcia_release(struct pcmcia_device *link)  { -	DEBUG(0, "das08_pcmcia_release(0x%p)\n", link); +	dev_dbg(&link->dev, "das08_pcmcia_release\n");  	pcmcia_disable_device(link);  }				/* das08_pcmcia_release */ @@ -477,14 +385,13 @@ struct pcmcia_driver das08_cs_driver = {  static int __init init_das08_pcmcia_cs(void)  { -	DEBUG(0, "%s\n", version);  	pcmcia_register_driver(&das08_cs_driver);  	return 0;  }  static void __exit exit_das08_pcmcia_cs(void)  { -	DEBUG(0, "das08_pcmcia_cs: unloading\n"); +	pr_debug("das08_pcmcia_cs: unloading\n");  	pcmcia_unregister_driver(&das08_cs_driver);  } diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c index ec31a397066..ef5e1183d47 100644 --- a/drivers/staging/comedi/drivers/ni_daq_700.c +++ b/drivers/staging/comedi/drivers/ni_daq_700.c @@ -436,25 +436,7 @@ static int dio700_detach(struct comedi_device *dev)  	return 0;  }; -/* PCMCIA crap */ - -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "ni_daq_700.c, based on dummy_cs.c"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ +/* PCMCIA crap -- watch your words, please! */  static void dio700_config(struct pcmcia_device *link);  static void dio700_release(struct pcmcia_device *link); @@ -510,7 +492,7 @@ static int dio700_cs_attach(struct pcmcia_device *link)  	printk(KERN_INFO "ni_daq_700:  cs-attach\n"); -	DEBUG(0, "dio700_cs_attach()\n"); +	dev_dbg(&link->dev, "dio700_cs_attach()\n");  	/* Allocate space for private device-specific data */  	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); @@ -521,7 +503,6 @@ static int dio700_cs_attach(struct pcmcia_device *link)  	/* Interrupt setup */  	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->irq.Handler = NULL;  	/* @@ -555,7 +536,7 @@ static void dio700_cs_detach(struct pcmcia_device *link)  	printk(KERN_INFO "ni_daq_700: cs-detach!\n"); -	DEBUG(0, "dio700_cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "dio700_cs_detach\n");  	if (link->dev_node) {  		((struct local_info_t *)link->priv)->stop = 1; @@ -576,141 +557,85 @@ static void dio700_cs_detach(struct pcmcia_device *link)  ======================================================================*/ -static void dio700_config(struct pcmcia_device *link) +static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data)  { -	struct local_info_t *dev = link->priv; -	tuple_t tuple; -	cisparse_t parse; -	int last_ret; -	u_char buf[64]; -	win_req_t req; +	win_req_t *req = priv_data;  	memreq_t map; -	cistpl_cftable_entry_t dflt = { 0 }; -	printk(KERN_INFO "ni_daq_700:  cs-config\n"); +	if (cfg->index == 0) +		return -ENODEV; -	DEBUG(0, "dio700_config(0x%p)\n", link); - -	/* -	   This reads the card's CONFIG tuple to find its configuration -	   registers. -	 */ -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	/* Does this card need audio output? */ +	if (cfg->flags & CISTPL_CFTABLE_AUDIO) { +		p_dev->conf.Attributes |= CONF_ENABLE_SPKR; +		p_dev->conf.Status = CCSR_AUDIO_ENA;  	} -	last_ret = pcmcia_get_tuple_data(link, &tuple); -	if (last_ret) { -		cs_error(link, GetTupleData, last_ret); -		goto cs_failed; -	} +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; -	last_ret = pcmcia_parse_tuple(&tuple, &parse); -	if (last_ret) { -		cs_error(link, ParseTuple, last_ret); -		goto cs_failed; +	/* IO window settings */ +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		} +		/* This reserves IO space but doesn't actually enable it */ +		if (pcmcia_request_io(p_dev, &p_dev->io) != 0) +			return -ENODEV;  	} -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; - -	/* -	   In this loop, we scan the CIS for configuration table entries, -	   each of which describes a valid card configuration, including -	   voltage, IO window, memory window, and interrupt settings. -	   We make no assumptions about the card to be configured: we use -	   just the information available in the CIS.  In an ideal world, -	   this would work for any PCMCIA card, but it requires a complete -	   and accurate CIS.  In practice, a driver usually "knows" most of -	   these things without consulting the CIS, and most client drivers -	   will only use the CIS to fill in implementation-defined details. -	 */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret != 0) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { +		cistpl_mem_t *mem = +			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem; +		req->Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; +		req->Attributes |= WIN_ENABLE; +		req->Base = mem->win[0].host_addr; +		req->Size = mem->win[0].len; +		if (req->Size < 0x1000) +			req->Size = 0x1000; +		req->AccessSpeed = 0; +		if (pcmcia_request_window(p_dev, req, &p_dev->win)) +			return -ENODEV; +		map.Page = 0; +		map.CardOffset = mem->win[0].card_addr; +		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map)) +			return -ENODEV;  	} -	while (1) { -		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -		if (pcmcia_get_tuple_data(link, &tuple) != 0) -			goto next_entry; -		if (pcmcia_parse_tuple(&tuple, &parse) != 0) -			goto next_entry; - -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; - -		/* Does this card need audio output? */ -		if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -			link->conf.Attributes |= CONF_ENABLE_SPKR; -			link->conf.Status = CCSR_AUDIO_ENA; -		} - -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; +	/* If we got this far, we're cool! */ +	return 0; +} -		/* IO window settings */ -		link->io.NumPorts1 = link->io.NumPorts2 = 0; -		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -			if (!(io->flags & CISTPL_IO_8BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -			if (!(io->flags & CISTPL_IO_16BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			link->io.NumPorts1 = io->win[0].len; -			if (io->nwin > 1) { -				link->io.Attributes2 = link->io.Attributes1; -				link->io.BasePort2 = io->win[1].base; -				link->io.NumPorts2 = io->win[1].len; -			} -			/* This reserves IO space but doesn't actually enable it */ -			if (pcmcia_request_io(link, &link->io) != 0) -				goto next_entry; -		} +static void dio700_config(struct pcmcia_device *link) +{ +	struct local_info_t *dev = link->priv; +	win_req_t req; +	int ret; -		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { -			cistpl_mem_t *mem = -			    (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; -			req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; -			req.Attributes |= WIN_ENABLE; -			req.Base = mem->win[0].host_addr; -			req.Size = mem->win[0].len; -			if (req.Size < 0x1000) -				req.Size = 0x1000; -			req.AccessSpeed = 0; -			if (pcmcia_request_window(&link, &req, &link->win)) -				goto next_entry; -			map.Page = 0; -			map.CardOffset = mem->win[0].card_addr; -			if (pcmcia_map_mem_page(link->win, &map)) -				goto next_entry; -		} -		/* If we got this far, we're cool! */ -		break; +	printk(KERN_INFO "ni_daq_700:  cs-config\n"); -next_entry: +	dev_dbg(&link->dev, "dio700_config\n"); -		last_ret = pcmcia_get_next_tuple(link, &tuple); -		if (last_ret) { -			cs_error(link, GetNextTuple, last_ret); -			goto cs_failed; -		} +	ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, &req); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		goto failed;  	}  	/* @@ -719,11 +644,9 @@ next_entry:  	   irq structure is initialized.  	 */  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		last_ret = pcmcia_request_irq(link, &link->irq); -		if (last_ret) { -			cs_error(link, RequestIRQ, last_ret); -			goto cs_failed; -		} +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/* @@ -731,11 +654,9 @@ next_entry:  	   the I/O windows and the interrupt mapping, and putting the  	   card and host interface into "Memory and IO" mode.  	 */ -	last_ret = pcmcia_request_configuration(link, &link->conf); -	if (last_ret != 0) { -		cs_error(link, RequestConfiguration, last_ret); -		goto cs_failed; -	} +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret != 0) +		goto failed;  	/*  	   At this point, the dev_node_t structure(s) need to be @@ -763,7 +684,7 @@ next_entry:  	return; -cs_failed: +failed:  	printk(KERN_INFO "ni_daq_700 cs failed");  	dio700_release(link); @@ -771,7 +692,7 @@ cs_failed:  static void dio700_release(struct pcmcia_device *link)  { -	DEBUG(0, "dio700_release(0x%p)\n", link); +	dev_dbg(&link->dev, "dio700_release\n");  	pcmcia_disable_device(link);  }				/* dio700_release */ @@ -830,15 +751,13 @@ struct pcmcia_driver dio700_cs_driver = {  static int __init init_dio700_cs(void)  { -	printk("ni_daq_700:  cs-init \n"); -	DEBUG(0, "%s\n", version);  	pcmcia_register_driver(&dio700_cs_driver);  	return 0;  }  static void __exit exit_dio700_cs(void)  { -	DEBUG(0, "ni_daq_700: unloading\n"); +	pr_debug("ni_daq_700: unloading\n");  	pcmcia_unregister_driver(&dio700_cs_driver);  } diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c index 0700a8bddd1..9017be3a92f 100644 --- a/drivers/staging/comedi/drivers/ni_daq_dio24.c +++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c @@ -187,25 +187,7 @@ static int dio24_detach(struct comedi_device *dev)  	return 0;  }; -/* PCMCIA crap */ - -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "ni_daq_dio24.c, based on dummy_cs.c"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ +/* PCMCIA crap -- watch your words! */  static void dio24_config(struct pcmcia_device *link);  static void dio24_release(struct pcmcia_device *link); @@ -261,7 +243,7 @@ static int dio24_cs_attach(struct pcmcia_device *link)  	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n"); -	DEBUG(0, "dio24_cs_attach()\n"); +	dev_dbg(&link->dev, "dio24_cs_attach()\n");  	/* Allocate space for private device-specific data */  	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); @@ -272,7 +254,6 @@ static int dio24_cs_attach(struct pcmcia_device *link)  	/* Interrupt setup */  	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->irq.Handler = NULL;  	/* @@ -306,7 +287,7 @@ static void dio24_cs_detach(struct pcmcia_device *link)  	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n"); -	DEBUG(0, "dio24_cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "dio24_cs_detach\n");  	if (link->dev_node) {  		((struct local_info_t *)link->priv)->stop = 1; @@ -327,142 +308,85 @@ static void dio24_cs_detach(struct pcmcia_device *link)  ======================================================================*/ -static void dio24_config(struct pcmcia_device *link) +static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data)  { -	struct local_info_t *dev = link->priv; -	tuple_t tuple; -	cisparse_t parse; -	int last_ret; -	u_char buf[64]; -	win_req_t req; +	win_req_t *req = priv_data;  	memreq_t map; -	cistpl_cftable_entry_t dflt = { 0 }; -	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n"); +	if (cfg->index == 0) +		return -ENODEV; -	DEBUG(0, "dio24_config(0x%p)\n", link); - -	/* -	   This reads the card's CONFIG tuple to find its configuration -	   registers. -	 */ -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	/* Does this card need audio output? */ +	if (cfg->flags & CISTPL_CFTABLE_AUDIO) { +		p_dev->conf.Attributes |= CONF_ENABLE_SPKR; +		p_dev->conf.Status = CCSR_AUDIO_ENA;  	} -	last_ret = pcmcia_get_tuple_data(link, &tuple); -	if (last_ret) { -		cs_error(link, GetTupleData, last_ret); -		goto cs_failed; -	} +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; -	last_ret = pcmcia_parse_tuple(&tuple, &parse); -	if (last_ret) { -		cs_error(link, ParseTuple, last_ret); -		goto cs_failed; +	/* IO window settings */ +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		} +		/* This reserves IO space but doesn't actually enable it */ +		if (pcmcia_request_io(p_dev, &p_dev->io) != 0) +			return -ENODEV;  	} -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; - -	/* -	   In this loop, we scan the CIS for configuration table entries, -	   each of which describes a valid card configuration, including -	   voltage, IO window, memory window, and interrupt settings. - -	   We make no assumptions about the card to be configured: we use -	   just the information available in the CIS.  In an ideal world, -	   this would work for any PCMCIA card, but it requires a complete -	   and accurate CIS.  In practice, a driver usually "knows" most of -	   these things without consulting the CIS, and most client drivers -	   will only use the CIS to fill in implementation-defined details. -	 */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { +		cistpl_mem_t *mem = +			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem; +		req->Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; +		req->Attributes |= WIN_ENABLE; +		req->Base = mem->win[0].host_addr; +		req->Size = mem->win[0].len; +		if (req->Size < 0x1000) +			req->Size = 0x1000; +		req->AccessSpeed = 0; +		if (pcmcia_request_window(p_dev, req, &p_dev->win)) +			return -ENODEV; +		map.Page = 0; +		map.CardOffset = mem->win[0].card_addr; +		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map)) +			return -ENODEV;  	} -	while (1) { -		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -		if (pcmcia_get_tuple_data(link, &tuple) != 0) -			goto next_entry; -		if (pcmcia_parse_tuple(&tuple, &parse) != 0) -			goto next_entry; - -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; - -		/* Does this card need audio output? */ -		if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -			link->conf.Attributes |= CONF_ENABLE_SPKR; -			link->conf.Status = CCSR_AUDIO_ENA; -		} - -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; +	/* If we got this far, we're cool! */ +	return 0; +} -		/* IO window settings */ -		link->io.NumPorts1 = link->io.NumPorts2 = 0; -		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -			if (!(io->flags & CISTPL_IO_8BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -			if (!(io->flags & CISTPL_IO_16BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			link->io.NumPorts1 = io->win[0].len; -			if (io->nwin > 1) { -				link->io.Attributes2 = link->io.Attributes1; -				link->io.BasePort2 = io->win[1].base; -				link->io.NumPorts2 = io->win[1].len; -			} -			/* This reserves IO space but doesn't actually enable it */ -			if (pcmcia_request_io(link, &link->io) != 0) -				goto next_entry; -		} +static void dio24_config(struct pcmcia_device *link) +{ +	struct local_info_t *dev = link->priv; +	int ret; +	win_req_t req; -		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { -			cistpl_mem_t *mem = -			    (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; -			req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; -			req.Attributes |= WIN_ENABLE; -			req.Base = mem->win[0].host_addr; -			req.Size = mem->win[0].len; -			if (req.Size < 0x1000) -				req.Size = 0x1000; -			req.AccessSpeed = 0; -			if (pcmcia_request_window(&link, &req, &link->win)) -				goto next_entry; -			map.Page = 0; -			map.CardOffset = mem->win[0].card_addr; -			if (pcmcia_map_mem_page(link->win, &map)) -				goto next_entry; -		} -		/* If we got this far, we're cool! */ -		break; +	printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n"); -next_entry: +	dev_dbg(&link->dev, "dio24_config\n"); -		last_ret = pcmcia_get_next_tuple(link, &tuple); -		if (last_ret) { -			cs_error(link, GetNextTuple, last_ret); -			goto cs_failed; -		} +	ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, &req); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		goto failed;  	}  	/* @@ -471,11 +395,9 @@ next_entry:  	   irq structure is initialized.  	 */  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		last_ret = pcmcia_request_irq(link, &link->irq); -		if (last_ret) { -			cs_error(link, RequestIRQ, last_ret); -			goto cs_failed; -		} +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/* @@ -483,11 +405,9 @@ next_entry:  	   the I/O windows and the interrupt mapping, and putting the  	   card and host interface into "Memory and IO" mode.  	 */ -	last_ret = pcmcia_request_configuration(link, &link->conf); -	if (last_ret) { -		cs_error(link, RequestConfiguration, last_ret); -		goto cs_failed; -	} +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/*  	   At this point, the dev_node_t structure(s) need to be @@ -515,7 +435,7 @@ next_entry:  	return; -cs_failed: +failed:  	printk(KERN_INFO "Fallo");  	dio24_release(link); @@ -523,7 +443,7 @@ cs_failed:  static void dio24_release(struct pcmcia_device *link)  { -	DEBUG(0, "dio24_release(0x%p)\n", link); +	dev_dbg(&link->dev, "dio24_release\n");  	pcmcia_disable_device(link);  }				/* dio24_release */ @@ -582,14 +502,12 @@ struct pcmcia_driver dio24_cs_driver = {  static int __init init_dio24_cs(void)  {  	printk("ni_daq_dio24: HOLA SOY YO!\n"); -	DEBUG(0, "%s\n", version);  	pcmcia_register_driver(&dio24_cs_driver);  	return 0;  }  static void __exit exit_dio24_cs(void)  { -	DEBUG(0, "ni_dio24: unloading\n");  	pcmcia_unregister_driver(&dio24_cs_driver);  } diff --git a/drivers/staging/comedi/drivers/ni_labpc_cs.c b/drivers/staging/comedi/drivers/ni_labpc_cs.c index a3053b8da1c..7d514b3ee75 100644 --- a/drivers/staging/comedi/drivers/ni_labpc_cs.c +++ b/drivers/staging/comedi/drivers/ni_labpc_cs.c @@ -153,23 +153,6 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)  	return labpc_common_attach(dev, iobase, irq, 0);  } -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static const char *version = -    "ni_labpc.c, based on dummy_cs.c 1.31 2001/08/24 12:13:13"; -#else -#define DEBUG(n, args...) -#endif -  /*====================================================================*/  /* @@ -236,7 +219,7 @@ static int labpc_cs_attach(struct pcmcia_device *link)  {  	struct local_info_t *local; -	DEBUG(0, "labpc_cs_attach()\n"); +	dev_dbg(&link->dev, "labpc_cs_attach()\n");  	/* Allocate space for private device-specific data */  	local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL); @@ -247,7 +230,6 @@ static int labpc_cs_attach(struct pcmcia_device *link)  	/* Interrupt setup */  	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FORCED_PULSE; -	link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_PULSE_ID;  	link->irq.Handler = NULL;  	/* @@ -278,7 +260,7 @@ static int labpc_cs_attach(struct pcmcia_device *link)  static void labpc_cs_detach(struct pcmcia_device *link)  { -	DEBUG(0, "labpc_cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "labpc_cs_detach\n");  	/*  	   If the device is currently configured and active, we won't @@ -305,135 +287,84 @@ static void labpc_cs_detach(struct pcmcia_device *link)  ======================================================================*/ -static void labpc_config(struct pcmcia_device *link) +static int labpc_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data)  { -	struct local_info_t *dev = link->priv; -	tuple_t tuple; -	cisparse_t parse; -	int last_ret; -	u_char buf[64]; -	win_req_t req; +	win_req_t *req = priv_data;  	memreq_t map; -	cistpl_cftable_entry_t dflt = { 0 }; -	DEBUG(0, "labpc_config(0x%p)\n", link); +	if (cfg->index == 0) +		return -ENODEV; -	/* -	   This reads the card's CONFIG tuple to find its configuration -	   registers. -	 */ -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	/* Does this card need audio output? */ +	if (cfg->flags & CISTPL_CFTABLE_AUDIO) { +		p_dev->conf.Attributes |= CONF_ENABLE_SPKR; +		p_dev->conf.Status = CCSR_AUDIO_ENA;  	} -	last_ret = pcmcia_get_tuple_data(link, &tuple); -	if (last_ret) { -		cs_error(link, GetTupleData, last_ret); -		goto cs_failed; -	} +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; -	last_ret = pcmcia_parse_tuple(&tuple, &parse); -	if (last_ret) { -		cs_error(link, ParseTuple, last_ret); -		goto cs_failed; +	/* IO window settings */ +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		} +		/* This reserves IO space but doesn't actually enable it */ +		if (pcmcia_request_io(p_dev, &p_dev->io) != 0) +			return -ENODEV;  	} -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; -	/* -	   In this loop, we scan the CIS for configuration table entries, -	   each of which describes a valid card configuration, including -	   voltage, IO window, memory window, and interrupt settings. - -	   We make no assumptions about the card to be configured: we use -	   just the information available in the CIS.  In an ideal world, -	   this would work for any PCMCIA card, but it requires a complete -	   and accurate CIS.  In practice, a driver usually "knows" most of -	   these things without consulting the CIS, and most client drivers -	   will only use the CIS to fill in implementation-defined details. -	 */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { +		cistpl_mem_t *mem = +			(cfg->mem.nwin) ? &cfg->mem : &dflt->mem; +		req->Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; +		req->Attributes |= WIN_ENABLE; +		req->Base = mem->win[0].host_addr; +		req->Size = mem->win[0].len; +		if (req->Size < 0x1000) +			req->Size = 0x1000; +		req->AccessSpeed = 0; +		if (pcmcia_request_window(p_dev, req, &p_dev->win)) +			return -ENODEV; +		map.Page = 0; +		map.CardOffset = mem->win[0].card_addr; +		if (pcmcia_map_mem_page(p_dev, p_dev->win, &map)) +			return -ENODEV;  	} -	while (1) { -		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -		if (pcmcia_get_tuple_data(link, &tuple)) -			goto next_entry; -		if (pcmcia_parse_tuple(&tuple, &parse)) -			goto next_entry; - -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; - -		/* Does this card need audio output? */ -		if (cfg->flags & CISTPL_CFTABLE_AUDIO) { -			link->conf.Attributes |= CONF_ENABLE_SPKR; -			link->conf.Status = CCSR_AUDIO_ENA; -		} +	/* If we got this far, we're cool! */ +	return 0; +} -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; -		/* IO window settings */ -		link->io.NumPorts1 = link->io.NumPorts2 = 0; -		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -			link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			link->io.NumPorts1 = io->win[0].len; -			if (io->nwin > 1) { -				link->io.Attributes2 = link->io.Attributes1; -				link->io.BasePort2 = io->win[1].base; -				link->io.NumPorts2 = io->win[1].len; -			} -			/* This reserves IO space but doesn't actually enable it */ -			if (pcmcia_request_io(link, &link->io)) -				goto next_entry; -		} +static void labpc_config(struct pcmcia_device *link) +{ +	struct local_info_t *dev = link->priv; +	int ret; +	win_req_t req; -		if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) { -			cistpl_mem_t *mem = -			    (cfg->mem.nwin) ? &cfg->mem : &dflt.mem; -			req.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM; -			req.Attributes |= WIN_ENABLE; -			req.Base = mem->win[0].host_addr; -			req.Size = mem->win[0].len; -			if (req.Size < 0x1000) -				req.Size = 0x1000; -			req.AccessSpeed = 0; -			link->win = (window_handle_t) link; -			if (pcmcia_request_window(&link, &req, &link->win)) -				goto next_entry; -			map.Page = 0; -			map.CardOffset = mem->win[0].card_addr; -			if (pcmcia_map_mem_page(link->win, &map)) -				goto next_entry; -		} -		/* If we got this far, we're cool! */ -		break; +	dev_dbg(&link->dev, "labpc_config\n"); -next_entry: -		last_ret = pcmcia_get_next_tuple(link, &tuple); -		if (last_ret) { -			cs_error(link, GetNextTuple, last_ret); -			goto cs_failed; -		} +	ret = pcmcia_loop_config(link, labpc_pcmcia_config_loop, &req); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		goto failed;  	}  	/* @@ -442,11 +373,9 @@ next_entry:  	   irq structure is initialized.  	 */  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		last_ret = pcmcia_request_irq(link, &link->irq); -		if (last_ret) { -			cs_error(link, RequestIRQ, last_ret); -			goto cs_failed; -		} +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/* @@ -454,11 +383,9 @@ next_entry:  	   the I/O windows and the interrupt mapping, and putting the  	   card and host interface into "Memory and IO" mode.  	 */ -	last_ret = pcmcia_request_configuration(link, &link->conf); -	if (last_ret) { -		cs_error(link, RequestConfiguration, last_ret); -		goto cs_failed; -	} +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/*  	   At this point, the dev_node_t structure(s) need to be @@ -486,14 +413,14 @@ next_entry:  	return; -cs_failed: +failed:  	labpc_release(link);  }				/* labpc_config */  static void labpc_release(struct pcmcia_device *link)  { -	DEBUG(0, "labpc_release(0x%p)\n", link); +	dev_dbg(&link->dev, "labpc_release\n");  	pcmcia_disable_device(link);  }				/* labpc_release */ @@ -551,14 +478,12 @@ struct pcmcia_driver labpc_cs_driver = {  static int __init init_labpc_cs(void)  { -	DEBUG(0, "%s\n", version);  	pcmcia_register_driver(&labpc_cs_driver);  	return 0;  }  static void __exit exit_labpc_cs(void)  { -	DEBUG(0, "ni_labpc: unloading\n");  	pcmcia_unregister_driver(&labpc_cs_driver);  } diff --git a/drivers/staging/comedi/drivers/ni_mio_cs.c b/drivers/staging/comedi/drivers/ni_mio_cs.c index 9aef87fc81d..d692f4bb47e 100644 --- a/drivers/staging/comedi/drivers/ni_mio_cs.c +++ b/drivers/staging/comedi/drivers/ni_mio_cs.c @@ -274,7 +274,6 @@ static int cs_attach(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;  	link->io.NumPorts1 = 16;  	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; @@ -312,96 +311,47 @@ static int mio_cs_resume(struct pcmcia_device *link)  	return 0;  } -static void mio_cs_config(struct pcmcia_device *link) -{ -	tuple_t tuple; -	u_short buf[128]; -	cisparse_t parse; -	int manfid = 0, prodid = 0; -	int ret; - -	DPRINTK("mio_cs_config(link=%p)\n", link); -	tuple.TupleData = (cisdata_t *) buf; -	tuple.TupleOffset = 0; -	tuple.TupleDataMax = 255; -	tuple.Attributes = 0; +static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data) +{ +	int base, ret; -	tuple.DesiredTuple = CISTPL_CONFIG; -	ret = pcmcia_get_first_tuple(link, &tuple); -	ret = pcmcia_get_tuple_data(link, &tuple); -	ret = pcmcia_parse_tuple(&tuple, &parse); -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; +	p_dev->io.NumPorts1 = cfg->io.win[0].len; +	p_dev->io.IOAddrLines = cfg->io.flags & CISTPL_IO_LINES_MASK; +	p_dev->io.NumPorts2 = 0; -#if 0 -	tuple.DesiredTuple = CISTPL_LONGLINK_MFC; -	tuple.Attributes = TUPLE_RETURN_COMMON | TUPLE_RETURN_LINK; -	info->multi(first_tuple(link, &tuple, &parse) == 0); -#endif - -	tuple.DesiredTuple = CISTPL_MANFID; -	tuple.Attributes = TUPLE_RETURN_COMMON; -	if ((pcmcia_get_first_tuple(link, &tuple) == 0) && -	    (pcmcia_get_tuple_data(link, &tuple) == 0)) { -		manfid = le16_to_cpu(buf[0]); -		prodid = le16_to_cpu(buf[1]); +	for (base = 0x000; base < 0x400; base += 0x20) { +		p_dev->io.BasePort1 = base; +		ret = pcmcia_request_io(p_dev, &p_dev->io); +		if (!ret) +			return 0;  	} -	/* printk("manfid = 0x%04x, 0x%04x\n",manfid,prodid); */ +	return -ENODEV; +} -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	tuple.Attributes = 0; -	ret = pcmcia_get_first_tuple(link, &tuple); -	ret = pcmcia_get_tuple_data(link, &tuple); -	ret = pcmcia_parse_tuple(&tuple, &parse); -#if 0 -	printk(" index: 0x%x\n", parse.cftable_entry.index); -	printk(" flags: 0x%x\n", parse.cftable_entry.flags); -	printk(" io flags: 0x%x\n", parse.cftable_entry.io.flags); -	printk(" io nwin: 0x%x\n", parse.cftable_entry.io.nwin); -	printk(" io base: 0x%x\n", parse.cftable_entry.io.win[0].base); -	printk(" io len: 0x%x\n", parse.cftable_entry.io.win[0].len); -	printk(" irq1: 0x%x\n", parse.cftable_entry.irq.IRQInfo1); -	printk(" irq2: 0x%x\n", parse.cftable_entry.irq.IRQInfo2); -	printk(" mem flags: 0x%x\n", parse.cftable_entry.mem.flags); -	printk(" mem nwin: 0x%x\n", parse.cftable_entry.mem.nwin); -	printk(" subtuples: 0x%x\n", parse.cftable_entry.subtuples); -#endif +static void mio_cs_config(struct pcmcia_device *link) +{ +	int ret; -#if 0 -	link->io.NumPorts1 = 0x20; -	link->io.IOAddrLines = 5; -	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -#endif -	link->io.NumPorts1 = parse.cftable_entry.io.win[0].len; -	link->io.IOAddrLines = -	    parse.cftable_entry.io.flags & CISTPL_IO_LINES_MASK; -	link->io.NumPorts2 = 0; +	DPRINTK("mio_cs_config(link=%p)\n", link); -	{ -		int base; -		for (base = 0x000; base < 0x400; base += 0x20) { -			link->io.BasePort1 = base; -			ret = pcmcia_request_io(link, &link->io); -			/* printk("RequestIO 0x%02x\n",ret); */ -			if (!ret) -				break; -		} +	ret = pcmcia_loop_config(link, mio_pcmcia_config_loop, NULL); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		return;  	} -	link->irq.IRQInfo1 = parse.cftable_entry.irq.IRQInfo1; -	link->irq.IRQInfo2 = parse.cftable_entry.irq.IRQInfo2;  	ret = pcmcia_request_irq(link, &link->irq);  	if (ret) {  		printk("pcmcia_request_irq() returned error: %i\n", ret);  	} -	/* printk("RequestIRQ 0x%02x\n",ret); */ - -	link->conf.ConfigIndex = 1;  	ret = pcmcia_request_configuration(link, &link->conf); -	/* printk("RequestConfiguration %d\n",ret); */  	link->dev_node = &dev_node;  } @@ -475,40 +425,17 @@ static int mio_cs_attach(struct comedi_device *dev, struct comedi_devconfig *it)  	return 0;  } -static int get_prodid(struct comedi_device *dev, struct pcmcia_device *link) -{ -	tuple_t tuple; -	u_short buf[128]; -	int prodid = 0; - -	tuple.TupleData = (cisdata_t *) buf; -	tuple.TupleOffset = 0; -	tuple.TupleDataMax = 255; -	tuple.DesiredTuple = CISTPL_MANFID; -	tuple.Attributes = TUPLE_RETURN_COMMON; -	if ((pcmcia_get_first_tuple(link, &tuple) == 0) && -	    (pcmcia_get_tuple_data(link, &tuple) == 0)) { -		prodid = le16_to_cpu(buf[1]); -	} - -	return prodid; -} -  static int ni_getboardtype(struct comedi_device *dev,  			   struct pcmcia_device *link)  { -	int id;  	int i; -	id = get_prodid(dev, link); -  	for (i = 0; i < n_ni_boards; i++) { -		if (ni_boards[i].device_id == id) { +		if (ni_boards[i].device_id == link->card_id)  			return i; -		}  	} -	printk("unknown board 0x%04x -- pretend it is a ", id); +	printk("unknown board 0x%04x -- pretend it is a ", link->card_id);  	return 0;  } diff --git a/drivers/staging/comedi/drivers/quatech_daqp_cs.c b/drivers/staging/comedi/drivers/quatech_daqp_cs.c index 344b82353e0..5256fd93316 100644 --- a/drivers/staging/comedi/drivers/quatech_daqp_cs.c +++ b/drivers/staging/comedi/drivers/quatech_daqp_cs.c @@ -55,23 +55,6 @@ Devices: [Quatech] DAQP-208 (daqp), DAQP-308  #include <pcmcia/cisreg.h>  #include <pcmcia/ds.h> -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "quatech_daqp_cs.c 1.10 2003/04/21 (Brent Baccala)"; -#else -#define DEBUG(n, args...) -#endif -  /* Maximum number of separate DAQP devices we'll allow */  #define MAX_DEV         4 @@ -863,8 +846,6 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)  {  	int ret;  	struct local_info_t *local = dev_table[it->options[0]]; -	tuple_t tuple; -	int i;  	struct comedi_subdevice *s;  	if (it->options[0] < 0 || it->options[0] >= MAX_DEV || !local) { @@ -883,29 +864,10 @@ static int daqp_attach(struct comedi_device *dev, struct comedi_devconfig *it)  	strcpy(local->board_name, "DAQP");  	dev->board_name = local->board_name; - -	tuple.DesiredTuple = CISTPL_VERS_1; -	if (pcmcia_get_first_tuple(local->link, &tuple) == 0) { -		u_char buf[128]; - -		buf[0] = buf[sizeof(buf) - 1] = 0; -		tuple.TupleData = buf; -		tuple.TupleDataMax = sizeof(buf); -		tuple.TupleOffset = 2; -		if (pcmcia_get_tuple_data(local->link, &tuple) == 0) { - -			for (i = 0; i < tuple.TupleDataLen - 4; i++) -				if (buf[i] == 0) -					break; -			for (i++; i < tuple.TupleDataLen - 4; i++) -				if (buf[i] == 0) -					break; -			i++; -			if ((i < tuple.TupleDataLen - 4) -			    && (strncmp(buf + i, "DAQP", 4) == 0)) { -				strncpy(local->board_name, buf + i, -					sizeof(local->board_name)); -			} +	if (local->link->prod_id[2]) { +		if (strncmp(local->link->prod_id[2], "DAQP", 4) == 0) { +			strncpy(local->board_name, local->link->prod_id[2], +				sizeof(local->board_name));  		}  	} @@ -1058,7 +1020,7 @@ static int daqp_cs_attach(struct pcmcia_device *link)  	struct local_info_t *local;  	int i; -	DEBUG(0, "daqp_cs_attach()\n"); +	dev_dbg(&link->dev, "daqp_cs_attach()\n");  	for (i = 0; i < MAX_DEV; i++)  		if (dev_table[i] == NULL) @@ -1079,10 +1041,8 @@ static int daqp_cs_attach(struct pcmcia_device *link)  	link->priv = local;  	/* Interrupt setup */ -	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID; +	link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;  	link->irq.Handler = daqp_interrupt; -	link->irq.Instance = local;  	/*  	   General socket configuration defaults can go here.  In this @@ -1112,7 +1072,7 @@ static void daqp_cs_detach(struct pcmcia_device *link)  {  	struct local_info_t *dev = link->priv; -	DEBUG(0, "daqp_cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "daqp_cs_detach\n");  	if (link->dev_node) {  		dev->stop = 1; @@ -1134,115 +1094,54 @@ static void daqp_cs_detach(struct pcmcia_device *link)  ======================================================================*/ -static void daqp_cs_config(struct pcmcia_device *link) -{ -	struct local_info_t *dev = link->priv; -	tuple_t tuple; -	cisparse_t parse; -	int last_ret; -	u_char buf[64]; - -	DEBUG(0, "daqp_cs_config(0x%p)\n", link); -	/* -	   This reads the card's CONFIG tuple to find its configuration -	   registers. -	 */ -	tuple.DesiredTuple = CISTPL_CONFIG; -	tuple.Attributes = 0; -	tuple.TupleData = buf; -	tuple.TupleDataMax = sizeof(buf); -	tuple.TupleOffset = 0; - -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; -	} - -	last_ret = pcmcia_get_tuple_data(link, &tuple); -	if (last_ret) { -		cs_error(link, GetTupleData, last_ret); -		goto cs_failed; -	} - -	last_ret = pcmcia_parse_tuple(&tuple, &parse); -	if (last_ret) { -		cs_error(link, ParseTuple, last_ret); -		goto cs_failed; -	} -	link->conf.ConfigBase = parse.config.base; -	link->conf.Present = parse.config.rmask[0]; +static int daqp_pcmcia_config_loop(struct pcmcia_device *p_dev, +				cistpl_cftable_entry_t *cfg, +				cistpl_cftable_entry_t *dflt, +				unsigned int vcc, +				void *priv_data) +{ +	if (cfg->index == 0) +		return -ENODEV; -	/* -	   In this loop, we scan the CIS for configuration table entries, -	   each of which describes a valid card configuration, including -	   voltage, IO window, memory window, and interrupt settings. +	/* Do we need to allocate an interrupt? */ +	if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) +		p_dev->conf.Attributes |= CONF_ENABLE_IRQ; -	   We make no assumptions about the card to be configured: we use -	   just the information available in the CIS.  In an ideal world, -	   this would work for any PCMCIA card, but it requires a complete -	   and accurate CIS.  In practice, a driver usually "knows" most of -	   these things without consulting the CIS, and most client drivers -	   will only use the CIS to fill in implementation-defined details. -	 */ -	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; -	last_ret = pcmcia_get_first_tuple(link, &tuple); -	if (last_ret) { -		cs_error(link, GetFirstTuple, last_ret); -		goto cs_failed; +	/* IO window settings */ +	p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; +	if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { +		cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; +		p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; +		if (!(io->flags & CISTPL_IO_8BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; +		if (!(io->flags & CISTPL_IO_16BIT)) +			p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; +		p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; +		p_dev->io.BasePort1 = io->win[0].base; +		p_dev->io.NumPorts1 = io->win[0].len; +		if (io->nwin > 1) { +			p_dev->io.Attributes2 = p_dev->io.Attributes1; +			p_dev->io.BasePort2 = io->win[1].base; +			p_dev->io.NumPorts2 = io->win[1].len; +		}  	} -	while (1) { -		cistpl_cftable_entry_t dflt = { 0 }; -		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); -		if (pcmcia_get_tuple_data(link, &tuple)) -			goto next_entry; -		if (pcmcia_parse_tuple(&tuple, &parse)) -			goto next_entry; - -		if (cfg->flags & CISTPL_CFTABLE_DEFAULT) -			dflt = *cfg; -		if (cfg->index == 0) -			goto next_entry; -		link->conf.ConfigIndex = cfg->index; - -		/* Do we need to allocate an interrupt? */ -		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) -			link->conf.Attributes |= CONF_ENABLE_IRQ; - -		/* IO window settings */ -		link->io.NumPorts1 = link->io.NumPorts2 = 0; -		if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { -			cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; -			link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; -			if (!(io->flags & CISTPL_IO_8BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; -			if (!(io->flags & CISTPL_IO_16BIT)) -				link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; -			link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; -			link->io.BasePort1 = io->win[0].base; -			link->io.NumPorts1 = io->win[0].len; -			if (io->nwin > 1) { -				link->io.Attributes2 = link->io.Attributes1; -				link->io.BasePort2 = io->win[1].base; -				link->io.NumPorts2 = io->win[1].len; -			} -		} +	/* This reserves IO space but doesn't actually enable it */ +	return pcmcia_request_io(p_dev, &p_dev->io); +} -		/* This reserves IO space but doesn't actually enable it */ -		if (pcmcia_request_io(link, &link->io)) -			goto next_entry; +static void daqp_cs_config(struct pcmcia_device *link) +{ +	struct local_info_t *dev = link->priv; +	int ret; -		/* If we got this far, we're cool! */ -		break; +	dev_dbg(&link->dev, "daqp_cs_config\n"); -next_entry: -		last_ret = pcmcia_get_next_tuple(link, &tuple); -		if (last_ret) { -			cs_error(link, GetNextTuple, last_ret); -			goto cs_failed; -		} +	ret = pcmcia_loop_config(link, daqp_pcmcia_config_loop, NULL); +	if (ret) { +		dev_warn(&link->dev, "no configuration found\n"); +		goto failed;  	}  	/* @@ -1251,11 +1150,9 @@ next_entry:  	   irq structure is initialized.  	 */  	if (link->conf.Attributes & CONF_ENABLE_IRQ) { -		last_ret = pcmcia_request_irq(link, &link->irq); -		if (last_ret) { -			cs_error(link, RequestIRQ, last_ret); -			goto cs_failed; -		} +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed;  	}  	/* @@ -1263,11 +1160,9 @@ next_entry:  	   the I/O windows and the interrupt mapping, and putting the  	   card and host interface into "Memory and IO" mode.  	 */ -	last_ret = pcmcia_request_configuration(link, &link->conf); -	if (last_ret) { -		cs_error(link, RequestConfiguration, last_ret); -		goto cs_failed; -	} +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	/*  	   At this point, the dev_node_t structure(s) need to be @@ -1296,14 +1191,14 @@ next_entry:  	return; -cs_failed: +failed:  	daqp_cs_release(link);  }				/* daqp_cs_config */  static void daqp_cs_release(struct pcmcia_device *link)  { -	DEBUG(0, "daqp_cs_release(0x%p)\n", link); +	dev_dbg(&link->dev, "daqp_cs_release\n");  	pcmcia_disable_device(link);  }				/* daqp_cs_release */ @@ -1363,7 +1258,6 @@ struct pcmcia_driver daqp_cs_driver = {  int __init init_module(void)  { -	DEBUG(0, "%s\n", version);  	pcmcia_register_driver(&daqp_cs_driver);  	comedi_driver_register(&driver_daqp);  	return 0; @@ -1371,7 +1265,6 @@ int __init init_module(void)  void __exit cleanup_module(void)  { -	DEBUG(0, "daqp_cs: unloading\n");  	comedi_driver_unregister(&driver_daqp);  	pcmcia_unregister_driver(&daqp_cs_driver);  } diff --git a/drivers/staging/netwave/netwave_cs.c b/drivers/staging/netwave/netwave_cs.c index 9498b46c99a..e61e6b9440a 100644 --- a/drivers/staging/netwave/netwave_cs.c +++ b/drivers/staging/netwave/netwave_cs.c @@ -145,23 +145,6 @@ static const unsigned int txConfEUD    = 0x10; /* Enable Uni-Data packets */  static const unsigned int txConfKey    = 0x02; /* Scramble data packets */  static const unsigned int txConfLoop   = 0x01; /* Loopback mode */ -/* -   All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If -   you do not define PCMCIA_DEBUG at all, all the debug code will be -   left out.  If you compile with PCMCIA_DEBUG=0, the debug code will -   be present but disabled -- but it can then be enabled for specific -   modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"netwave_cs.c 0.3.0 Thu Jul 17 14:36:02 1997 (John Markus Bjørndalen)\n"; -#else -#define DEBUG(n, args...) -#endif  /*====================================================================*/ @@ -383,7 +366,7 @@ static int netwave_probe(struct pcmcia_device *link)      struct net_device *dev;      netwave_private *priv; -    DEBUG(0, "netwave_attach()\n"); +    dev_dbg(&link->dev, "netwave_attach()\n");      /* Initialize the struct pcmcia_device structure */      dev = alloc_etherdev(sizeof(netwave_private)); @@ -401,8 +384,7 @@ static int netwave_probe(struct pcmcia_device *link)      link->io.IOAddrLines = 5;      /* Interrupt setup */ -    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -    link->irq.IRQInfo1 = IRQ_LEVEL_ID; +    link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;      link->irq.Handler = &netwave_interrupt;      /* General socket configuration */ @@ -421,8 +403,6 @@ static int netwave_probe(struct pcmcia_device *link)      dev->watchdog_timeo = TX_TIMEOUT; -    link->irq.Instance = dev; -      return netwave_pcmcia_config( link);  } /* netwave_attach */ @@ -438,7 +418,7 @@ static void netwave_detach(struct pcmcia_device *link)  {  	struct net_device *dev = link->priv; -	DEBUG(0, "netwave_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "netwave_detach\n");  	netwave_release(link); @@ -725,18 +705,15 @@ static const struct iw_handler_def	netwave_handler_def =   *   */ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static int netwave_pcmcia_config(struct pcmcia_device *link) {      struct net_device *dev = link->priv;      netwave_private *priv = netdev_priv(dev); -    int i, j, last_ret, last_fn; +    int i, j, ret;      win_req_t req;      memreq_t mem;      u_char __iomem *ramBase = NULL; -    DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link); +    dev_dbg(&link->dev, "netwave_pcmcia_config\n");      /*       *  Try allocating IO ports.  This tries a few fixed addresses. @@ -749,22 +726,24 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {  	if (i == 0)  		break;      } -    if (i != 0) { -	cs_error(link, RequestIO, i); +    if (i != 0)  	goto failed; -    }      /*       *  Now allocate an interrupt line.  Note that this does not       *  actually assign a handler to the interrupt.       */ -    CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); +    ret = pcmcia_request_irq(link, &link->irq); +    if (ret) +	    goto failed;      /*       *  This actually configures the PCMCIA socket -- setting up       *  the I/O windows and the interrupt mapping.       */ -    CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); +    ret = pcmcia_request_configuration(link, &link->conf); +    if (ret) +	    goto failed;      /*       *  Allocate a 32K memory window.  Note that the struct pcmcia_device @@ -772,14 +751,18 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {       *  device needs several windows, you'll need to keep track of       *  the handles in your private data structure, dev->priv.       */ -    DEBUG(1, "Setting mem speed of %d\n", mem_speed); +    dev_dbg(&link->dev, "Setting mem speed of %d\n", mem_speed);      req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE;      req.Base = 0; req.Size = 0x8000;      req.AccessSpeed = mem_speed; -    CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); +    ret = pcmcia_request_window(link, &req, &link->win); +    if (ret) +	    goto failed;      mem.CardOffset = 0x20000; mem.Page = 0;  -    CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); +    ret = pcmcia_map_mem_page(link, link->win, &mem); +    if (ret) +	    goto failed;      /* Store base address of the common window frame */      ramBase = ioremap(req.Base, 0x8000); @@ -787,7 +770,7 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {      dev->irq = link->irq.AssignedIRQ;      dev->base_addr = link->io.BasePort1; -    SET_NETDEV_DEV(dev, &handle_to_dev(link)); +    SET_NETDEV_DEV(dev, &link->dev);      if (register_netdev(dev) != 0) {  	printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); @@ -818,8 +801,6 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {  	   get_uint16(ramBase + NETWAVE_EREG_ARW+2));      return 0; -cs_failed: -    cs_error(link, last_fn, last_ret);  failed:      netwave_release(link);      return -ENODEV; @@ -837,7 +818,7 @@ static void netwave_release(struct pcmcia_device *link)  	struct net_device *dev = link->priv;  	netwave_private *priv = netdev_priv(dev); -	DEBUG(0, "netwave_release(0x%p)\n", link); +	dev_dbg(&link->dev, "netwave_release\n");  	pcmcia_disable_device(link);  	if (link->win) @@ -892,7 +873,7 @@ static void netwave_reset(struct net_device *dev) {      u_char __iomem *ramBase = priv->ramBase;      unsigned int iobase = dev->base_addr; -    DEBUG(0, "netwave_reset: Done with hardware reset\n"); +    pr_debug("netwave_reset: Done with hardware reset\n");      priv->timeoutCounter = 0; @@ -988,7 +969,7 @@ static int netwave_hw_xmit(unsigned char* data, int len,      dev->stats.tx_bytes += len; -    DEBUG(3, "Transmitting with SPCQ %x SPU %x LIF %x ISPLQ %x\n", +    pr_debug("Transmitting with SPCQ %x SPU %x LIF %x ISPLQ %x\n",  	  readb(ramBase + NETWAVE_EREG_SPCQ),  	  readb(ramBase + NETWAVE_EREG_SPU),  	  readb(ramBase + NETWAVE_EREG_LIF), @@ -1000,7 +981,7 @@ static int netwave_hw_xmit(unsigned char* data, int len,      MaxData    = get_uint16(ramBase + NETWAVE_EREG_TDP+2);      DataOffset = get_uint16(ramBase + NETWAVE_EREG_TDP+4); -    DEBUG(3, "TxFreeList %x, MaxData %x, DataOffset %x\n", +    pr_debug("TxFreeList %x, MaxData %x, DataOffset %x\n",  	  TxFreeList, MaxData, DataOffset);      /* Copy packet to the adapter fragment buffers */ @@ -1088,7 +1069,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id)          status = inb(iobase + NETWAVE_REG_ASR);  	if (!pcmcia_dev_present(link)) { -	    DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " +	    pr_debug("netwave_interrupt: Interrupt with status 0x%x "  		  "from removed or suspended card!\n", status);  	    break;  	} @@ -1132,7 +1113,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id)  	    int txStatus;  	    txStatus = readb(ramBase + NETWAVE_EREG_TSER); -	    DEBUG(3, "Transmit done. TSER = %x id %x\n",  +	    pr_debug("Transmit done. TSER = %x id %x\n",  		  txStatus, readb(ramBase + NETWAVE_EREG_TSER + 1));  	    if (txStatus & 0x20) { @@ -1156,7 +1137,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id)  		 *      TxGU and TxNOAP is set. (Those are the only ones  		 *      to set TxErr).  		 */ -		DEBUG(3, "netwave_interrupt: TxDN with error status %x\n",  +		pr_debug("netwave_interrupt: TxDN with error status %x\n",  		      txStatus);  		/* Clear out TxGU, TxNOAP, TxErr and TxTrys */ @@ -1164,7 +1145,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id)  		writeb(0xdf & txStatus, ramBase+NETWAVE_EREG_TSER+4);  		++dev->stats.tx_errors;  	    } -	    DEBUG(3, "New status is TSER %x ASR %x\n", +	    pr_debug("New status is TSER %x ASR %x\n",  		  readb(ramBase + NETWAVE_EREG_TSER),  		  inb(iobase + NETWAVE_REG_ASR)); @@ -1172,7 +1153,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id)  	}  	/* TxBA, this would trigger on all error packets received */  	/* if (status & 0x01) { -	   DEBUG(4, "Transmit buffers available, %x\n", status); +	   pr_debug("Transmit buffers available, %x\n", status);  	   }  	   */      } @@ -1190,7 +1171,7 @@ static irqreturn_t netwave_interrupt(int irq, void* dev_id)   */  static void netwave_watchdog(struct net_device *dev) { -    DEBUG(1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name); +    pr_debug("%s: netwave_watchdog: watchdog timer expired\n", dev->name);      netwave_reset(dev);      dev->trans_start = jiffies;      netif_wake_queue(dev); @@ -1211,7 +1192,7 @@ static int netwave_rx(struct net_device *dev)      int i;      u_char *ptr; -    DEBUG(3, "xinw_rx: Receiving ... \n"); +    pr_debug("xinw_rx: Receiving ... \n");      /* Receive max 10 packets for now. */      for (i = 0; i < 10; i++) { @@ -1237,7 +1218,7 @@ static int netwave_rx(struct net_device *dev)  	skb = dev_alloc_skb(rcvLen+5);  	if (skb == NULL) { -	    DEBUG(1, "netwave_rx: Could not allocate an sk_buff of " +	    pr_debug("netwave_rx: Could not allocate an sk_buff of "  		  "length %d\n", rcvLen);  	    ++dev->stats.rx_dropped;  	    /* Tell the adapter to skip the packet */ @@ -1279,7 +1260,7 @@ static int netwave_rx(struct net_device *dev)  	wait_WOC(iobase);  	writeb(NETWAVE_CMD_SRP, ramBase + NETWAVE_EREG_CB + 0);  	writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 1); -	DEBUG(3, "Packet reception ok\n"); +	pr_debug("Packet reception ok\n");      }      return 0;  } @@ -1288,7 +1269,7 @@ static int netwave_open(struct net_device *dev) {      netwave_private *priv = netdev_priv(dev);      struct pcmcia_device *link = priv->p_dev; -    DEBUG(1, "netwave_open: starting.\n"); +    dev_dbg(&link->dev, "netwave_open: starting.\n");      if (!pcmcia_dev_present(link))  	return -ENODEV; @@ -1305,7 +1286,7 @@ static int netwave_close(struct net_device *dev) {      netwave_private *priv = netdev_priv(dev);      struct pcmcia_device *link = priv->p_dev; -    DEBUG(1, "netwave_close: finishing.\n"); +    dev_dbg(&link->dev, "netwave_close: finishing.\n");      link->open--;      netif_stop_queue(dev); @@ -1358,11 +1339,11 @@ static void set_multicast_list(struct net_device *dev)      u_char  rcvMode = 0;  #ifdef PCMCIA_DEBUG -    if (pc_debug > 2) { -	static int old; +    { +	xstatic int old;  	if (old != dev->mc_count) {  	    old = dev->mc_count; -	    DEBUG(0, "%s: setting Rx mode to %d addresses.\n", +	    pr_debug("%s: setting Rx mode to %d addresses.\n",  		  dev->name, dev->mc_count);  	}      } diff --git a/drivers/staging/wavelan/wavelan_cs.c b/drivers/staging/wavelan/wavelan_cs.c index 431a20ec6db..33918fd5b23 100644 --- a/drivers/staging/wavelan/wavelan_cs.c +++ b/drivers/staging/wavelan/wavelan_cs.c @@ -3656,10 +3656,7 @@ wv_pcmcia_reset(struct net_device *	dev)    i = pcmcia_access_configuration_register(link, ®);    if (i != 0) -    { -      cs_error(link, AccessConfigurationRegister, i);        return FALSE; -    }  #ifdef DEBUG_CONFIG_INFO    printk(KERN_DEBUG "%s: wavelan_pcmcia_reset(): Config reg is 0x%x\n", @@ -3670,19 +3667,13 @@ wv_pcmcia_reset(struct net_device *	dev)    reg.Value = reg.Value | COR_SW_RESET;    i = pcmcia_access_configuration_register(link, ®);    if (i != 0) -    { -      cs_error(link, AccessConfigurationRegister, i);        return FALSE; -    }    reg.Action = CS_WRITE;    reg.Value = COR_LEVEL_IRQ | COR_CONFIG;    i = pcmcia_access_configuration_register(link, ®);    if (i != 0) -    { -      cs_error(link, AccessConfigurationRegister, i);        return FALSE; -    }  #ifdef DEBUG_CONFIG_TRACE    printk(KERN_DEBUG "%s: <-wv_pcmcia_reset()\n", dev->name); @@ -3857,10 +3848,7 @@ wv_pcmcia_config(struct pcmcia_device *	link)      {        i = pcmcia_request_io(link, &link->io);        if (i != 0) -	{ -	  cs_error(link, RequestIO, i);  	  break; -	}        /*         * Now allocate an interrupt line.  Note that this does not @@ -3868,10 +3856,7 @@ wv_pcmcia_config(struct pcmcia_device *	link)         */        i = pcmcia_request_irq(link, &link->irq);        if (i != 0) -	{ -	  cs_error(link, RequestIRQ, i);  	  break; -	}        /*         * This actually configures the PCMCIA socket -- setting up @@ -3880,10 +3865,7 @@ wv_pcmcia_config(struct pcmcia_device *	link)        link->conf.ConfigIndex = 1;        i = pcmcia_request_configuration(link, &link->conf);        if (i != 0) -	{ -	  cs_error(link, RequestConfiguration, i);  	  break; -	}        /*         * Allocate a small memory window.  Note that the struct pcmcia_device @@ -3894,24 +3876,18 @@ wv_pcmcia_config(struct pcmcia_device *	link)        req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;        req.Base = req.Size = 0;        req.AccessSpeed = mem_speed; -      i = pcmcia_request_window(&link, &req, &link->win); +      i = pcmcia_request_window(link, &req, &link->win);        if (i != 0) -	{ -	  cs_error(link, RequestWindow, i);  	  break; -	}        lp->mem = ioremap(req.Base, req.Size);        dev->mem_start = (u_long)lp->mem;        dev->mem_end = dev->mem_start + req.Size;        mem.CardOffset = 0; mem.Page = 0; -      i = pcmcia_map_mem_page(link->win, &mem); +      i = pcmcia_map_mem_page(link, link->win, &mem);        if (i != 0) -	{ -	  cs_error(link, MapMemPage, i);  	  break; -	}        /* Feed device with this info... */        dev->irq = link->irq.AssignedIRQ; @@ -3923,7 +3899,7 @@ wv_pcmcia_config(struct pcmcia_device *	link)  	     lp->mem, dev->irq, (u_int) dev->base_addr);  #endif -      SET_NETDEV_DEV(dev, &handle_to_dev(link)); +      SET_NETDEV_DEV(dev, &link->dev);        i = register_netdev(dev);        if(i != 0)  	{ @@ -4462,8 +4438,7 @@ wavelan_probe(struct pcmcia_device *p_dev)    p_dev->io.IOAddrLines = 3;    /* Interrupt setup */ -  p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; -  p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; +  p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING;    p_dev->irq.Handler = wavelan_interrupt;    /* General socket configuration */ @@ -4475,7 +4450,7 @@ wavelan_probe(struct pcmcia_device *p_dev)    if (!dev)        return -ENOMEM; -  p_dev->priv = p_dev->irq.Instance = dev; +  p_dev->priv = dev;    lp = netdev_priv(dev); diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index 347c3ed1d9f..d442fd35620 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -19,13 +19,6 @@   *	PCMCIA service support for Quicknet cards   */ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0644); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -#else -#define DEBUG(n, args...) -#endif  typedef struct ixj_info_t {  	int ndev; @@ -39,7 +32,7 @@ static void ixj_cs_release(struct pcmcia_device * link);  static int ixj_probe(struct pcmcia_device *p_dev)  { -	DEBUG(0, "ixj_attach()\n"); +	dev_dbg(&p_dev->dev, "ixj_attach()\n");  	/* Create new ixj device */  	p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;  	p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8; @@ -55,33 +48,30 @@ static int ixj_probe(struct pcmcia_device *p_dev)  static void ixj_detach(struct pcmcia_device *link)  { -	DEBUG(0, "ixj_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "ixj_detach\n");  	ixj_cs_release(link);          kfree(link->priv);  } -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -  static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)  {  	char *str;  	int i, place; -	DEBUG(0, "ixj_get_serial(0x%p)\n", link); +	dev_dbg(&link->dev, "ixj_get_serial\n");  	str = link->prod_id[0];  	if (!str) -		goto cs_failed; +		goto failed;  	printk("%s", str);  	str = link->prod_id[1];  	if (!str) -		goto cs_failed; +		goto failed;  	printk(" %s", str);  	str = link->prod_id[2];  	if (!str) -		goto cs_failed; +		goto failed;  	place = 1;  	for (i = strlen(str) - 1; i >= 0; i--) {  		switch (str[i]) { @@ -118,9 +108,9 @@ static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)  	}  	str = link->prod_id[3];  	if (!str) -		goto cs_failed; +		goto failed;  	printk(" version %s\n", str); -      cs_failed: +failed:  	return;  } @@ -151,13 +141,13 @@ static int ixj_config(struct pcmcia_device * link)  	cistpl_cftable_entry_t dflt = { 0 };  	info = link->priv; -	DEBUG(0, "ixj_config(0x%p)\n", link); +	dev_dbg(&link->dev, "ixj_config\n");  	if (pcmcia_loop_config(link, ixj_config_check, &dflt)) -		goto cs_failed; +		goto failed;  	if (pcmcia_request_configuration(link, &link->conf)) -		goto cs_failed; +		goto failed;  	/*   	 *	Register the card with the core. @@ -170,7 +160,7 @@ static int ixj_config(struct pcmcia_device * link)  	ixj_get_serial(link, j);  	return 0; -      cs_failed: +failed:  	ixj_cs_release(link);  	return -ENODEV;  } @@ -178,7 +168,7 @@ static int ixj_config(struct pcmcia_device * link)  static void ixj_cs_release(struct pcmcia_device *link)  {  	ixj_info_t *info = link->priv; -	DEBUG(0, "ixj_cs_release(0x%p)\n", link); +	dev_dbg(&link->dev, "ixj_cs_release\n");  	info->ndev = 0;  	pcmcia_disable_device(link);  } diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c index 516848dd9b4..39d253e841f 100644 --- a/drivers/usb/host/sl811_cs.c +++ b/drivers/usb/host/sl811_cs.c @@ -37,28 +37,8 @@ MODULE_LICENSE("GPL");  /* MACROS                                                             */  /*====================================================================*/ -#if defined(DEBUG) || defined(PCMCIA_DEBUG) - -static int pc_debug = 0; -module_param(pc_debug, int, 0644); - -#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args) - -#else -#define DBG(n, args...) do{}while(0) -#endif	/* no debugging */ -  #define INFO(args...) printk(KERN_INFO "sl811_cs: " args) -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444) - -#define CS_CHECK(fn, ret) \ -	do { \ -		last_fn = (fn); \ -		if ((last_ret = (ret)) != 0) \ -			goto cs_failed; \ -	} while (0) -  /*====================================================================*/  /* VARIABLES                                                          */  /*====================================================================*/ @@ -76,7 +56,7 @@ static void sl811_cs_release(struct pcmcia_device * link);  static void release_platform_dev(struct device * dev)  { -	DBG(0, "sl811_cs platform_dev release\n"); +	dev_dbg(dev, "sl811_cs platform_dev release\n");  	dev->parent = NULL;  } @@ -140,7 +120,7 @@ static int sl811_hc_init(struct device *parent, resource_size_t base_addr,  static void sl811_cs_detach(struct pcmcia_device *link)  { -	DBG(0, "sl811_cs_detach(0x%p)\n", link); +	dev_dbg(&link->dev, "sl811_cs_detach\n");  	sl811_cs_release(link); @@ -150,7 +130,7 @@ static void sl811_cs_detach(struct pcmcia_device *link)  static void sl811_cs_release(struct pcmcia_device * link)  { -	DBG(0, "sl811_cs_release(0x%p)\n", link); +	dev_dbg(&link->dev, "sl811_cs_release\n");  	pcmcia_disable_device(link);  	platform_device_unregister(&platform_dev); @@ -205,11 +185,11 @@ static int sl811_cs_config_check(struct pcmcia_device *p_dev,  static int sl811_cs_config(struct pcmcia_device *link)  { -	struct device		*parent = &handle_to_dev(link); +	struct device		*parent = &link->dev;  	local_info_t		*dev = link->priv; -	int			last_fn, last_ret; +	int			ret; -	DBG(0, "sl811_cs_config(0x%p)\n", link); +	dev_dbg(&link->dev, "sl811_cs_config\n");  	if (pcmcia_loop_config(link, sl811_cs_config_check, NULL))  		goto failed; @@ -217,14 +197,16 @@ static int sl811_cs_config(struct pcmcia_device *link)  	/* require an IRQ and two registers */  	if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)  		goto failed; -	if (link->conf.Attributes & CONF_ENABLE_IRQ) -		CS_CHECK(RequestIRQ, -			pcmcia_request_irq(link, &link->irq)); -	else +	if (link->conf.Attributes & CONF_ENABLE_IRQ) { +		ret = pcmcia_request_irq(link, &link->irq); +		if (ret) +			goto failed; +	} else  		goto failed; -	CS_CHECK(RequestConfiguration, -		pcmcia_request_configuration(link, &link->conf)); +	ret = pcmcia_request_configuration(link, &link->conf); +	if (ret) +		goto failed;  	sprintf(dev->node.dev_name, driver_name);  	dev->node.major = dev->node.minor = 0; @@ -241,8 +223,6 @@ static int sl811_cs_config(struct pcmcia_device *link)  	if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)  			< 0) { -cs_failed: -		cs_error(link, last_fn, last_ret);  failed:  		printk(KERN_WARNING "sl811_cs_config failed\n");  		sl811_cs_release(link); @@ -263,7 +243,6 @@ static int sl811_cs_probe(struct pcmcia_device *link)  	/* Initialize */  	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -	link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;  	link->irq.Handler = NULL;  	link->conf.Attributes = 0; diff --git a/drivers/video/da8xx-fb.c b/drivers/video/da8xx-fb.c index 035d56835b7..ea1fd3f4751 100644 --- a/drivers/video/da8xx-fb.c +++ b/drivers/video/da8xx-fb.c @@ -554,11 +554,11 @@ static int fb_check_var(struct fb_var_screeninfo *var,  		var->transp.length = 0;  		break;  	case 16:		/* RGB 565 */ -		var->red.offset = 0; +		var->red.offset = 11;  		var->red.length = 5;  		var->green.offset = 5;  		var->green.length = 6; -		var->blue.offset = 11; +		var->blue.offset = 0;  		var->blue.length = 5;  		var->transp.offset = 0;  		var->transp.length = 0; @@ -591,7 +591,7 @@ static int __devexit fb_remove(struct platform_device *dev)  		unregister_framebuffer(info);  		fb_dealloc_cmap(&info->cmap);  		dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, -					info->screen_base, +					info->screen_base - PAGE_SIZE,  					info->fix.smem_start);  		free_irq(par->irq, par);  		clk_disable(par->lcdc_clk); @@ -749,6 +749,7 @@ static int __init fb_probe(struct platform_device *device)  				(PAGE_SIZE - par->palette_sz);  	/* the rest of the frame buffer is pixel data */ +	da8xx_fb_info->screen_base = par->v_palette_base + par->palette_sz;  	da8xx_fb_fix.smem_start = par->p_palette_base + par->palette_sz;  	da8xx_fb_fix.smem_len = par->databuf_sz - par->palette_sz;  	da8xx_fb_fix.line_length = (lcdc_info->width * lcd_cfg->bpp) / 8; @@ -787,6 +788,8 @@ static int __init fb_probe(struct platform_device *device)  	da8xx_fb_info->var = da8xx_fb_var;  	da8xx_fb_info->fbops = &da8xx_fb_ops;  	da8xx_fb_info->pseudo_palette = par->pseudo_palette; +	da8xx_fb_info->fix.visual = (da8xx_fb_info->var.bits_per_pixel <= 8) ? +				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;  	ret = fb_alloc_cmap(&da8xx_fb_info->cmap, PALETTE_SIZE, 0);  	if (ret) @@ -825,7 +828,7 @@ err_free_irq:  err_release_fb_mem:  	dma_free_coherent(NULL, par->databuf_sz + PAGE_SIZE, -				da8xx_fb_info->screen_base, +				da8xx_fb_info->screen_base - PAGE_SIZE,  				da8xx_fb_info->fix.smem_start);  err_release_fb: diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index 1a83709f961..f67db426837 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1147,7 +1147,7 @@ static int __init gbefb_probe(struct platform_device *p_dev)  	gbefb_setup(options);  #endif -	if (!request_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) { +	if (!request_mem_region(GBE_BASE, sizeof(struct sgi_gbe), "GBE")) {  		printk(KERN_ERR "gbefb: couldn't reserve mmio region\n");  		ret = -EBUSY;  		goto out_release_framebuffer; diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index f6cccc9df02..bf12d06b587 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -62,7 +62,7 @@ extern unsigned int idt_cpu_freq;  static int timeout = WATCHDOG_TIMEOUT;  module_param(timeout, int, 0);  MODULE_PARM_DESC(timeout, "Watchdog timeout value, in seconds (default=" -		WATCHDOG_TIMEOUT ")"); +		__MODULE_STRING(WATCHDOG_TIMEOUT) ")");  static int nowayout = WATCHDOG_NOWAYOUT;  module_param(nowayout, int, 0); @@ -276,7 +276,7 @@ static int __devinit rc32434_wdt_probe(struct platform_device *pdev)  		return -ENODEV;  	} -	wdt_reg = ioremap_nocache(r->start, r->end - r->start); +	wdt_reg = ioremap_nocache(r->start, resource_size(r));  	if (!wdt_reg) {  		printk(KERN_ERR PFX "failed to remap I/O resources\n");  		return -ENXIO; diff --git a/fs/exec.c b/fs/exec.c index ba112bd4a33..c0c636e34f6 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -46,7 +46,6 @@  #include <linux/proc_fs.h>  #include <linux/mount.h>  #include <linux/security.h> -#include <linux/ima.h>  #include <linux/syscalls.h>  #include <linux/tsacct_kern.h>  #include <linux/cn_proc.h> @@ -1209,9 +1208,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)  	retval = security_bprm_check(bprm);  	if (retval)  		return retval; -	retval = ima_bprm_check(bprm); -	if (retval) -		return retval;  	/* kernel module loader fixup */  	/* so we don't try to load run modprobe in kernel space. */ diff --git a/fs/file_table.c b/fs/file_table.c index 8eb44042e00..4bef4c01ec6 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -13,7 +13,6 @@  #include <linux/module.h>  #include <linux/fs.h>  #include <linux/security.h> -#include <linux/ima.h>  #include <linux/eventpoll.h>  #include <linux/rcupdate.h>  #include <linux/mount.h> @@ -280,7 +279,6 @@ void __fput(struct file *file)  	if (file->f_op && file->f_op->release)  		file->f_op->release(inode, file);  	security_file_free(file); -	ima_file_free(file);  	if (unlikely(S_ISCHR(inode->i_mode) && inode->i_cdev != NULL))  		cdev_put(inode->i_cdev);  	fops_put(file->f_op); diff --git a/fs/gfs2/Kconfig b/fs/gfs2/Kconfig index 5971359d209..4dcddf83326 100644 --- a/fs/gfs2/Kconfig +++ b/fs/gfs2/Kconfig @@ -8,6 +8,8 @@ config GFS2_FS  	select FS_POSIX_ACL  	select CRC32  	select SLOW_WORK +	select QUOTA +	select QUOTACTL  	help  	  A cluster filesystem. diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 3fc4e3ac7d8..3eb1ea84617 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -12,6 +12,7 @@  #include <linux/spinlock.h>  #include <linux/completion.h>  #include <linux/buffer_head.h> +#include <linux/xattr.h>  #include <linux/posix_acl.h>  #include <linux/posix_acl_xattr.h>  #include <linux/gfs2_ondisk.h> @@ -26,108 +27,44 @@  #include "trans.h"  #include "util.h" -#define ACL_ACCESS 1 -#define ACL_DEFAULT 0 - -int gfs2_acl_validate_set(struct gfs2_inode *ip, int access, -			  struct gfs2_ea_request *er, int *remove, mode_t *mode) +static const char *gfs2_acl_name(int type)  { -	struct posix_acl *acl; -	int error; - -	error = gfs2_acl_validate_remove(ip, access); -	if (error) -		return error; - -	if (!er->er_data) -		return -EINVAL; - -	acl = posix_acl_from_xattr(er->er_data, er->er_data_len); -	if (IS_ERR(acl)) -		return PTR_ERR(acl); -	if (!acl) { -		*remove = 1; -		return 0; -	} - -	error = posix_acl_valid(acl); -	if (error) -		goto out; - -	if (access) { -		error = posix_acl_equiv_mode(acl, mode); -		if (!error) -			*remove = 1; -		else if (error > 0) -			error = 0; +	switch (type) { +	case ACL_TYPE_ACCESS: +		return GFS2_POSIX_ACL_ACCESS; +	case ACL_TYPE_DEFAULT: +		return GFS2_POSIX_ACL_DEFAULT;  	} - -out: -	posix_acl_release(acl); -	return error; -} - -int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access) -{ -	if (!GFS2_SB(&ip->i_inode)->sd_args.ar_posix_acl) -		return -EOPNOTSUPP; -	if (!is_owner_or_cap(&ip->i_inode)) -		return -EPERM; -	if (S_ISLNK(ip->i_inode.i_mode)) -		return -EOPNOTSUPP; -	if (!access && !S_ISDIR(ip->i_inode.i_mode)) -		return -EACCES; - -	return 0; +	return NULL;  } -static int acl_get(struct gfs2_inode *ip, const char *name, -		   struct posix_acl **acl, struct gfs2_ea_location *el, -		   char **datap, unsigned int *lenp) +static struct posix_acl *gfs2_acl_get(struct gfs2_inode *ip, int type)  { +	struct posix_acl *acl; +	const char *name;  	char *data; -	unsigned int len; -	int error; - -	el->el_bh = NULL; +	int len;  	if (!ip->i_eattr) -		return 0; - -	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, el); -	if (error) -		return error; -	if (!el->el_ea) -		return 0; -	if (!GFS2_EA_DATA_LEN(el->el_ea)) -		goto out; +		return NULL; -	len = GFS2_EA_DATA_LEN(el->el_ea); -	data = kmalloc(len, GFP_NOFS); -	error = -ENOMEM; -	if (!data) -		goto out; +	acl = get_cached_acl(&ip->i_inode, type); +	if (acl != ACL_NOT_CACHED) +		return acl; -	error = gfs2_ea_get_copy(ip, el, data, len); -	if (error < 0) -		goto out_kfree; -	error = 0; +	name = gfs2_acl_name(type); +	if (name == NULL) +		return ERR_PTR(-EINVAL); -	if (acl) { -		*acl = posix_acl_from_xattr(data, len); -		if (IS_ERR(*acl)) -			error = PTR_ERR(*acl); -	} +	len = gfs2_xattr_acl_get(ip, name, &data); +	if (len < 0) +		return ERR_PTR(len); +	if (len == 0) +		return NULL; -out_kfree: -	if (error || !datap) { -		kfree(data); -	} else { -		*datap = data; -		*lenp = len; -	} -out: -	return error; +	acl = posix_acl_from_xattr(data, len); +	kfree(data); +	return acl;  }  /** @@ -140,14 +77,12 @@ out:  int gfs2_check_acl(struct inode *inode, int mask)  { -	struct gfs2_ea_location el; -	struct posix_acl *acl = NULL; +	struct posix_acl *acl;  	int error; -	error = acl_get(GFS2_I(inode), GFS2_POSIX_ACL_ACCESS, &acl, &el, NULL, NULL); -	brelse(el.el_bh); -	if (error) -		return error; +	acl = gfs2_acl_get(GFS2_I(inode), ACL_TYPE_ACCESS); +	if (IS_ERR(acl)) +		return PTR_ERR(acl);  	if (acl) {  		error = posix_acl_permission(inode, acl, mask); @@ -158,57 +93,75 @@ int gfs2_check_acl(struct inode *inode, int mask)  	return -EAGAIN;  } -static int munge_mode(struct gfs2_inode *ip, mode_t mode) +static int gfs2_set_mode(struct inode *inode, mode_t mode)  { -	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); -	struct buffer_head *dibh; -	int error; +	int error = 0; -	error = gfs2_trans_begin(sdp, RES_DINODE, 0); -	if (error) -		return error; +	if (mode != inode->i_mode) { +		struct iattr iattr; -	error = gfs2_meta_inode_buffer(ip, &dibh); -	if (!error) { -		gfs2_assert_withdraw(sdp, -				(ip->i_inode.i_mode & S_IFMT) == (mode & S_IFMT)); -		ip->i_inode.i_mode = mode; -		gfs2_trans_add_bh(ip->i_gl, dibh, 1); -		gfs2_dinode_out(ip, dibh->b_data); -		brelse(dibh); +		iattr.ia_valid = ATTR_MODE; +		iattr.ia_mode = mode; + +		error = gfs2_setattr_simple(GFS2_I(inode), &iattr);  	} -	gfs2_trans_end(sdp); +	return error; +} + +static int gfs2_acl_set(struct inode *inode, int type, struct posix_acl *acl) +{ +	int error; +	int len; +	char *data; +	const char *name = gfs2_acl_name(type); -	return 0; +	BUG_ON(name == NULL); +	len = posix_acl_to_xattr(acl, NULL, 0); +	if (len == 0) +		return 0; +	data = kmalloc(len, GFP_NOFS); +	if (data == NULL) +		return -ENOMEM; +	error = posix_acl_to_xattr(acl, data, len); +	if (error < 0) +		goto out; +	error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, data, len, 0); +	if (!error) +		set_cached_acl(inode, type, acl); +out: +	kfree(data); +	return error;  } -int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) +int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode)  { -	struct gfs2_ea_location el;  	struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); -	struct posix_acl *acl = NULL, *clone; -	mode_t mode = ip->i_inode.i_mode; -	char *data = NULL; -	unsigned int len; -	int error; +	struct posix_acl *acl, *clone; +	mode_t mode = inode->i_mode; +	int error = 0;  	if (!sdp->sd_args.ar_posix_acl)  		return 0; -	if (S_ISLNK(ip->i_inode.i_mode)) +	if (S_ISLNK(inode->i_mode))  		return 0; -	error = acl_get(dip, GFS2_POSIX_ACL_DEFAULT, &acl, &el, &data, &len); -	brelse(el.el_bh); -	if (error) -		return error; +	acl = gfs2_acl_get(dip, ACL_TYPE_DEFAULT); +	if (IS_ERR(acl)) +		return PTR_ERR(acl);  	if (!acl) {  		mode &= ~current_umask(); -		if (mode != ip->i_inode.i_mode) -			error = munge_mode(ip, mode); +		if (mode != inode->i_mode) +			error = gfs2_set_mode(inode, mode);  		return error;  	} +	if (S_ISDIR(inode->i_mode)) { +		error = gfs2_acl_set(inode, ACL_TYPE_DEFAULT, acl); +		if (error) +			goto out; +	} +  	clone = posix_acl_clone(acl, GFP_NOFS);  	error = -ENOMEM;  	if (!clone) @@ -216,43 +169,32 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip)  	posix_acl_release(acl);  	acl = clone; -	if (S_ISDIR(ip->i_inode.i_mode)) { -		error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS, -				       GFS2_POSIX_ACL_DEFAULT, data, len, 0); -		if (error) -			goto out; -	} -  	error = posix_acl_create_masq(acl, &mode);  	if (error < 0)  		goto out;  	if (error == 0)  		goto munge; -	posix_acl_to_xattr(acl, data, len); -	error = gfs2_xattr_set(&ip->i_inode, GFS2_EATYPE_SYS, -			       GFS2_POSIX_ACL_ACCESS, data, len, 0); +	error = gfs2_acl_set(inode, ACL_TYPE_ACCESS, acl);  	if (error)  		goto out;  munge: -	error = munge_mode(ip, mode); +	error = gfs2_set_mode(inode, mode);  out:  	posix_acl_release(acl); -	kfree(data);  	return error;  }  int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)  { -	struct posix_acl *acl = NULL, *clone; -	struct gfs2_ea_location el; +	struct posix_acl *acl, *clone;  	char *data;  	unsigned int len;  	int error; -	error = acl_get(ip, GFS2_POSIX_ACL_ACCESS, &acl, &el, &data, &len); -	if (error) -		goto out_brelse; +	acl = gfs2_acl_get(ip, ACL_TYPE_ACCESS); +	if (IS_ERR(acl)) +		return PTR_ERR(acl);  	if (!acl)  		return gfs2_setattr_simple(ip, attr); @@ -265,15 +207,134 @@ int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr)  	error = posix_acl_chmod_masq(acl, attr->ia_mode);  	if (!error) { +		len = posix_acl_to_xattr(acl, NULL, 0); +		data = kmalloc(len, GFP_NOFS); +		error = -ENOMEM; +		if (data == NULL) +			goto out;  		posix_acl_to_xattr(acl, data, len); -		error = gfs2_ea_acl_chmod(ip, &el, attr, data); +		error = gfs2_xattr_acl_chmod(ip, attr, data); +		kfree(data); +		set_cached_acl(&ip->i_inode, ACL_TYPE_ACCESS, acl);  	}  out:  	posix_acl_release(acl); -	kfree(data); -out_brelse: -	brelse(el.el_bh);  	return error;  } +static int gfs2_acl_type(const char *name) +{ +	if (strcmp(name, GFS2_POSIX_ACL_ACCESS) == 0) +		return ACL_TYPE_ACCESS; +	if (strcmp(name, GFS2_POSIX_ACL_DEFAULT) == 0) +		return ACL_TYPE_DEFAULT; +	return -EINVAL; +} + +static int gfs2_xattr_system_get(struct inode *inode, const char *name, +				 void *buffer, size_t size) +{ +	struct posix_acl *acl; +	int type; +	int error; + +	type = gfs2_acl_type(name); +	if (type < 0) +		return type; + +	acl = gfs2_acl_get(GFS2_I(inode), type); +	if (IS_ERR(acl)) +		return PTR_ERR(acl); +	if (acl == NULL) +		return -ENODATA; + +	error = posix_acl_to_xattr(acl, buffer, size); +	posix_acl_release(acl); + +	return error; +} + +static int gfs2_xattr_system_set(struct inode *inode, const char *name, +				 const void *value, size_t size, int flags) +{ +	struct gfs2_sbd *sdp = GFS2_SB(inode); +	struct posix_acl *acl = NULL; +	int error = 0, type; + +	if (!sdp->sd_args.ar_posix_acl) +		return -EOPNOTSUPP; + +	type = gfs2_acl_type(name); +	if (type < 0) +		return type; +	if (flags & XATTR_CREATE) +		return -EINVAL; +	if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) +		return value ? -EACCES : 0; +	if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) +		return -EPERM; +	if (S_ISLNK(inode->i_mode)) +		return -EOPNOTSUPP; + +	if (!value) +		goto set_acl; + +	acl = posix_acl_from_xattr(value, size); +	if (!acl) { +		/* +		 * acl_set_file(3) may request that we set default ACLs with +		 * zero length -- defend (gracefully) against that here. +		 */ +		goto out; +	} +	if (IS_ERR(acl)) { +		error = PTR_ERR(acl); +		goto out; +	} + +	error = posix_acl_valid(acl); +	if (error) +		goto out_release; + +	error = -EINVAL; +	if (acl->a_count > GFS2_ACL_MAX_ENTRIES) +		goto out_release; + +	if (type == ACL_TYPE_ACCESS) { +		mode_t mode = inode->i_mode; +		error = posix_acl_equiv_mode(acl, &mode); + +		if (error <= 0) { +			posix_acl_release(acl); +			acl = NULL; + +			if (error < 0) +				return error; +		} + +		error = gfs2_set_mode(inode, mode); +		if (error) +			goto out_release; +	} + +set_acl: +	error = gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, 0); +	if (!error) { +		if (acl) +			set_cached_acl(inode, type, acl); +		else +			forget_cached_acl(inode, type); +	} +out_release: +	posix_acl_release(acl); +out: +	return error; +} + +struct xattr_handler gfs2_xattr_system_handler = { +	.prefix = XATTR_SYSTEM_PREFIX, +	.get    = gfs2_xattr_system_get, +	.set    = gfs2_xattr_system_set, +}; + diff --git a/fs/gfs2/acl.h b/fs/gfs2/acl.h index 6751930bfb6..9306a2e6620 100644 --- a/fs/gfs2/acl.h +++ b/fs/gfs2/acl.h @@ -13,26 +13,12 @@  #include "incore.h"  #define GFS2_POSIX_ACL_ACCESS		"posix_acl_access" -#define GFS2_POSIX_ACL_ACCESS_LEN	16  #define GFS2_POSIX_ACL_DEFAULT		"posix_acl_default" -#define GFS2_POSIX_ACL_DEFAULT_LEN	17 +#define GFS2_ACL_MAX_ENTRIES		25 -#define GFS2_ACL_IS_ACCESS(name, len) \ -         ((len) == GFS2_POSIX_ACL_ACCESS_LEN && \ -         !memcmp(GFS2_POSIX_ACL_ACCESS, (name), (len))) - -#define GFS2_ACL_IS_DEFAULT(name, len) \ -         ((len) == GFS2_POSIX_ACL_DEFAULT_LEN && \ -         !memcmp(GFS2_POSIX_ACL_DEFAULT, (name), (len))) - -struct gfs2_ea_request; - -int gfs2_acl_validate_set(struct gfs2_inode *ip, int access, -			  struct gfs2_ea_request *er, -			  int *remove, mode_t *mode); -int gfs2_acl_validate_remove(struct gfs2_inode *ip, int access); -int gfs2_check_acl(struct inode *inode, int mask); -int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip); -int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); +extern int gfs2_check_acl(struct inode *inode, int mask); +extern int gfs2_acl_create(struct gfs2_inode *dip, struct inode *inode); +extern int gfs2_acl_chmod(struct gfs2_inode *ip, struct iattr *attr); +extern struct xattr_handler gfs2_xattr_system_handler;  #endif /* __ACL_DOT_H__ */ diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 694b5d48f03..7b8da941526 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -269,7 +269,6 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,  	pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;  	unsigned offset = i_size & (PAGE_CACHE_SIZE-1);  	unsigned nrblocks = nr_pages * (PAGE_CACHE_SIZE/inode->i_sb->s_blocksize); -	struct backing_dev_info *bdi = mapping->backing_dev_info;  	int i;  	int ret; @@ -313,11 +312,6 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,  		if (ret || (--(wbc->nr_to_write) <= 0))  			ret = 1; -		if (wbc->nonblocking && bdi_write_congested(bdi)) { -			wbc->encountered_congestion = 1; -			ret = 1; -		} -  	}  	gfs2_trans_end(sdp);  	return ret; @@ -338,7 +332,6 @@ static int gfs2_write_jdata_pagevec(struct address_space *mapping,  static int gfs2_write_cache_jdata(struct address_space *mapping,  				  struct writeback_control *wbc)  { -	struct backing_dev_info *bdi = mapping->backing_dev_info;  	int ret = 0;  	int done = 0;  	struct pagevec pvec; @@ -348,11 +341,6 @@ static int gfs2_write_cache_jdata(struct address_space *mapping,  	int scanned = 0;  	int range_whole = 0; -	if (wbc->nonblocking && bdi_write_congested(bdi)) { -		wbc->encountered_congestion = 1; -		return 0; -	} -  	pagevec_init(&pvec, 0);  	if (wbc->range_cyclic) {  		index = mapping->writeback_index; /* Start from prev offset */ @@ -819,8 +807,10 @@ static int gfs2_stuffed_write_end(struct inode *inode, struct buffer_head *dibh,  		mark_inode_dirty(inode);  	} -	if (inode == sdp->sd_rindex) +	if (inode == sdp->sd_rindex) {  		adjust_fs_space(inode); +		ip->i_gh.gh_flags |= GL_NOCACHE; +	}  	brelse(dibh);  	gfs2_trans_end(sdp); @@ -889,8 +879,10 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,  		mark_inode_dirty(inode);  	} -	if (inode == sdp->sd_rindex) +	if (inode == sdp->sd_rindex) {  		adjust_fs_space(inode); +		ip->i_gh.gh_flags |= GL_NOCACHE; +	}  	brelse(dibh);  	gfs2_trans_end(sdp); diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 297d7e5ceba..25fddc100f1 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -525,38 +525,6 @@ consist_inode:  	return ERR_PTR(-EIO);  } - -/** - * dirent_first - Return the first dirent - * @dip: the directory - * @bh: The buffer - * @dent: Pointer to list of dirents - * - * return first dirent whether bh points to leaf or stuffed dinode - * - * Returns: IS_LEAF, IS_DINODE, or -errno - */ - -static int dirent_first(struct gfs2_inode *dip, struct buffer_head *bh, -			struct gfs2_dirent **dent) -{ -	struct gfs2_meta_header *h = (struct gfs2_meta_header *)bh->b_data; - -	if (be32_to_cpu(h->mh_type) == GFS2_METATYPE_LF) { -		if (gfs2_meta_check(GFS2_SB(&dip->i_inode), bh)) -			return -EIO; -		*dent = (struct gfs2_dirent *)(bh->b_data + -					       sizeof(struct gfs2_leaf)); -		return IS_LEAF; -	} else { -		if (gfs2_metatype_check(GFS2_SB(&dip->i_inode), bh, GFS2_METATYPE_DI)) -			return -EIO; -		*dent = (struct gfs2_dirent *)(bh->b_data + -					       sizeof(struct gfs2_dinode)); -		return IS_DINODE; -	} -} -  static int dirent_check_reclen(struct gfs2_inode *dip,  			       const struct gfs2_dirent *d, const void *end_p)  { @@ -1006,7 +974,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)  	divider = (start + half_len) << (32 - dip->i_depth);  	/*  Copy the entries  */ -	dirent_first(dip, obh, &dent); +	dent = (struct gfs2_dirent *)(obh->b_data + sizeof(struct gfs2_leaf));  	do {  		next = dent; diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 8b674b1f3a5..f455a03a09e 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -241,15 +241,14 @@ int gfs2_glock_put(struct gfs2_glock *gl)  	int rv = 0;  	write_lock(gl_lock_addr(gl->gl_hash)); -	if (atomic_dec_and_test(&gl->gl_ref)) { +	if (atomic_dec_and_lock(&gl->gl_ref, &lru_lock)) {  		hlist_del(&gl->gl_list); -		write_unlock(gl_lock_addr(gl->gl_hash)); -		spin_lock(&lru_lock);  		if (!list_empty(&gl->gl_lru)) {  			list_del_init(&gl->gl_lru);  			atomic_dec(&lru_count);  		}  		spin_unlock(&lru_lock); +		write_unlock(gl_lock_addr(gl->gl_hash));  		GLOCK_BUG_ON(gl, !list_empty(&gl->gl_holders));  		glock_free(gl);  		rv = 1; @@ -513,7 +512,6 @@ retry:  			GLOCK_BUG_ON(gl, 1);  		}  		spin_unlock(&gl->gl_spin); -		gfs2_glock_put(gl);  		return;  	} @@ -524,8 +522,6 @@ retry:  		if (glops->go_xmote_bh) {  			spin_unlock(&gl->gl_spin);  			rv = glops->go_xmote_bh(gl, gh); -			if (rv == -EAGAIN) -				return;  			spin_lock(&gl->gl_spin);  			if (rv) {  				do_error(gl, rv); @@ -540,7 +536,6 @@ out:  	clear_bit(GLF_LOCK, &gl->gl_flags);  out_locked:  	spin_unlock(&gl->gl_spin); -	gfs2_glock_put(gl);  }  static unsigned int gfs2_lm_lock(struct gfs2_sbd *sdp, void *lock, @@ -600,7 +595,6 @@ __acquires(&gl->gl_spin)  	if (!(ret & LM_OUT_ASYNC)) {  		finish_xmote(gl, ret); -		gfs2_glock_hold(gl);  		if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)  			gfs2_glock_put(gl);  	} else { @@ -672,12 +666,17 @@ out:  	return;  out_sched: +	clear_bit(GLF_LOCK, &gl->gl_flags); +	smp_mb__after_clear_bit();  	gfs2_glock_hold(gl);  	if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)  		gfs2_glock_put_nolock(gl); +	return; +  out_unlock:  	clear_bit(GLF_LOCK, &gl->gl_flags); -	goto out; +	smp_mb__after_clear_bit(); +	return;  }  static void delete_work_func(struct work_struct *work) @@ -707,9 +706,12 @@ static void glock_work_func(struct work_struct *work)  {  	unsigned long delay = 0;  	struct gfs2_glock *gl = container_of(work, struct gfs2_glock, gl_work.work); +	int drop_ref = 0; -	if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) +	if (test_and_clear_bit(GLF_REPLY_PENDING, &gl->gl_flags)) {  		finish_xmote(gl, gl->gl_reply); +		drop_ref = 1; +	}  	down_read(&gfs2_umount_flush_sem);  	spin_lock(&gl->gl_spin);  	if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && @@ -727,6 +729,8 @@ static void glock_work_func(struct work_struct *work)  	if (!delay ||  	    queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0)  		gfs2_glock_put(gl); +	if (drop_ref) +		gfs2_glock_put(gl);  }  /** @@ -1361,10 +1365,6 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)  		list_del_init(&gl->gl_lru);  		atomic_dec(&lru_count); -		/* Check if glock is about to be freed */ -		if (atomic_read(&gl->gl_ref) == 0) -			continue; -  		/* Test for being demotable */  		if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {  			gfs2_glock_hold(gl); @@ -1375,10 +1375,11 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)  				handle_callback(gl, LM_ST_UNLOCKED, 0);  				nr--;  			} +			clear_bit(GLF_LOCK, &gl->gl_flags); +			smp_mb__after_clear_bit();  			if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)  				gfs2_glock_put_nolock(gl);  			spin_unlock(&gl->gl_spin); -			clear_bit(GLF_LOCK, &gl->gl_flags);  			spin_lock(&lru_lock);  			continue;  		} diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index c609894ec0d..13f0bd22813 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h @@ -180,15 +180,6 @@ static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl)  	return gl->gl_state == LM_ST_SHARED;  } -static inline int gfs2_glock_is_blocking(struct gfs2_glock *gl) -{ -	int ret; -	spin_lock(&gl->gl_spin); -	ret = test_bit(GLF_DEMOTE, &gl->gl_flags); -	spin_unlock(&gl->gl_spin); -	return ret; -} -  int gfs2_glock_get(struct gfs2_sbd *sdp,  		   u64 number, const struct gfs2_glock_operations *glops,  		   int create, struct gfs2_glock **glp); diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 6985eef06c3..78554acc060 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -13,6 +13,7 @@  #include <linux/buffer_head.h>  #include <linux/gfs2_ondisk.h>  #include <linux/bio.h> +#include <linux/posix_acl.h>  #include "gfs2.h"  #include "incore.h" @@ -184,8 +185,10 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags)  	if (flags & DIO_METADATA) {  		struct address_space *mapping = gl->gl_aspace->i_mapping;  		truncate_inode_pages(mapping, 0); -		if (ip) +		if (ip) {  			set_bit(GIF_INVALID, &ip->i_flags); +			forget_all_cached_acls(&ip->i_inode); +		}  	}  	if (ip == GFS2_I(gl->gl_sbd->sd_rindex)) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 6edb423f90b..4792200978c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -429,7 +429,11 @@ struct gfs2_args {  	unsigned int ar_meta:1;			/* mount metafs */  	unsigned int ar_discard:1;		/* discard requests */  	unsigned int ar_errors:2;               /* errors=withdraw | panic */ +	unsigned int ar_nobarrier:1;            /* do not send barriers */  	int ar_commit;				/* Commit interval */ +	int ar_statfs_quantum;			/* The fast statfs interval */ +	int ar_quota_quantum;			/* The quota interval */ +	int ar_statfs_percent;			/* The % change to force sync */  };  struct gfs2_tune { @@ -558,6 +562,7 @@ struct gfs2_sbd {  	spinlock_t sd_statfs_spin;  	struct gfs2_statfs_change_host sd_statfs_master;  	struct gfs2_statfs_change_host sd_statfs_local; +	int sd_statfs_force_sync;  	/* Resource group stuff */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index fb15d3b1f40..26ba2a4c4a2 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -871,7 +871,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,  	if (error)  		goto fail_gunlock2; -	error = gfs2_acl_create(dip, GFS2_I(inode)); +	error = gfs2_acl_create(dip, inode);  	if (error)  		goto fail_gunlock2; @@ -947,9 +947,7 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf)  	str->di_header.mh_magic = cpu_to_be32(GFS2_MAGIC);  	str->di_header.mh_type = cpu_to_be32(GFS2_METATYPE_DI); -	str->di_header.__pad0 = 0;  	str->di_header.mh_format = cpu_to_be32(GFS2_FORMAT_DI); -	str->di_header.__pad1 = 0;  	str->di_num.no_addr = cpu_to_be64(ip->i_no_addr);  	str->di_num.no_formal_ino = cpu_to_be64(ip->i_no_formal_ino);  	str->di_mode = cpu_to_be32(ip->i_inode.i_mode); diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 13c6237c5f6..4511b08fc45 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -596,7 +596,9 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags, int pull)  	memset(lh, 0, sizeof(struct gfs2_log_header));  	lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);  	lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); +	lh->lh_header.__pad0 = cpu_to_be64(0);  	lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); +	lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);  	lh->lh_sequence = cpu_to_be64(sdp->sd_log_sequence++);  	lh->lh_flags = cpu_to_be32(flags);  	lh->lh_tail = cpu_to_be32(tail); diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 9969ff062c5..de97632ba32 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -132,6 +132,7 @@ static struct buffer_head *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type)  static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)  {  	struct gfs2_bufdata *bd = container_of(le, struct gfs2_bufdata, bd_le); +	struct gfs2_meta_header *mh;  	struct gfs2_trans *tr;  	lock_buffer(bd->bd_bh); @@ -148,6 +149,9 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le)  	set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);  	gfs2_meta_check(sdp, bd->bd_bh);  	gfs2_pin(sdp, bd->bd_bh); +	mh = (struct gfs2_meta_header *)bd->bd_bh->b_data; +	mh->__pad0 = cpu_to_be64(0); +	mh->mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);  	sdp->sd_log_num_buf++;  	list_add(&le->le_list, &sdp->sd_log_le_buf);  	tr->tr_num_buf_new++; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 52fb6c04898..edfee24f363 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -18,6 +18,7 @@  #include <linux/mount.h>  #include <linux/gfs2_ondisk.h>  #include <linux/slow-work.h> +#include <linux/quotaops.h>  #include "gfs2.h"  #include "incore.h" @@ -62,13 +63,10 @@ static void gfs2_tune_init(struct gfs2_tune *gt)  	gt->gt_quota_warn_period = 10;  	gt->gt_quota_scale_num = 1;  	gt->gt_quota_scale_den = 1; -	gt->gt_quota_quantum = 60;  	gt->gt_new_files_jdata = 0;  	gt->gt_max_readahead = 1 << 18;  	gt->gt_stall_secs = 600;  	gt->gt_complain_secs = 10; -	gt->gt_statfs_quantum = 30; -	gt->gt_statfs_slow = 0;  }  static struct gfs2_sbd *init_sbd(struct super_block *sb) @@ -1114,7 +1112,7 @@ void gfs2_online_uevent(struct gfs2_sbd *sdp)   * Returns: errno   */ -static int fill_super(struct super_block *sb, void *data, int silent) +static int fill_super(struct super_block *sb, struct gfs2_args *args, int silent)  {  	struct gfs2_sbd *sdp;  	struct gfs2_holder mount_gh; @@ -1125,17 +1123,7 @@ static int fill_super(struct super_block *sb, void *data, int silent)  		printk(KERN_WARNING "GFS2: can't alloc struct gfs2_sbd\n");  		return -ENOMEM;  	} - -	sdp->sd_args.ar_quota = GFS2_QUOTA_DEFAULT; -	sdp->sd_args.ar_data = GFS2_DATA_DEFAULT; -	sdp->sd_args.ar_commit = 60; -	sdp->sd_args.ar_errors = GFS2_ERRORS_DEFAULT; - -	error = gfs2_mount_args(sdp, &sdp->sd_args, data); -	if (error) { -		printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); -		goto fail; -	} +	sdp->sd_args = *args;  	if (sdp->sd_args.ar_spectator) {                  sb->s_flags |= MS_RDONLY; @@ -1143,11 +1131,15 @@ static int fill_super(struct super_block *sb, void *data, int silent)  	}  	if (sdp->sd_args.ar_posix_acl)  		sb->s_flags |= MS_POSIXACL; +	if (sdp->sd_args.ar_nobarrier) +		set_bit(SDF_NOBARRIERS, &sdp->sd_flags);  	sb->s_magic = GFS2_MAGIC;  	sb->s_op = &gfs2_super_ops;  	sb->s_export_op = &gfs2_export_ops;  	sb->s_xattr = gfs2_xattr_handlers; +	sb->s_qcop = &gfs2_quotactl_ops; +	sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE;  	sb->s_time_gran = 1;  	sb->s_maxbytes = MAX_LFS_FILESIZE; @@ -1160,6 +1152,15 @@ static int fill_super(struct super_block *sb, void *data, int silent)  	sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;  	sdp->sd_tune.gt_log_flush_secs = sdp->sd_args.ar_commit; +	sdp->sd_tune.gt_quota_quantum = sdp->sd_args.ar_quota_quantum; +	if (sdp->sd_args.ar_statfs_quantum) { +		sdp->sd_tune.gt_statfs_slow = 0; +		sdp->sd_tune.gt_statfs_quantum = sdp->sd_args.ar_statfs_quantum; +	} +	else { +		sdp->sd_tune.gt_statfs_slow = 1; +		sdp->sd_tune.gt_statfs_quantum = 30; +	}  	error = init_names(sdp, silent);  	if (error) @@ -1243,18 +1244,127 @@ fail:  	return error;  } -static int gfs2_get_sb(struct file_system_type *fs_type, int flags, -		       const char *dev_name, void *data, struct vfsmount *mnt) +static int set_gfs2_super(struct super_block *s, void *data)  { -	return get_sb_bdev(fs_type, flags, dev_name, data, fill_super, mnt); +	s->s_bdev = data; +	s->s_dev = s->s_bdev->bd_dev; + +	/* +	 * We set the bdi here to the queue backing, file systems can +	 * overwrite this in ->fill_super() +	 */ +	s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info; +	return 0;  } -static int test_meta_super(struct super_block *s, void *ptr) +static int test_gfs2_super(struct super_block *s, void *ptr)  {  	struct block_device *bdev = ptr;  	return (bdev == s->s_bdev);  } +/** + * gfs2_get_sb - Get the GFS2 superblock + * @fs_type: The GFS2 filesystem type + * @flags: Mount flags + * @dev_name: The name of the device + * @data: The mount arguments + * @mnt: The vfsmnt for this mount + * + * Q. Why not use get_sb_bdev() ? + * A. We need to select one of two root directories to mount, independent + *    of whether this is the initial, or subsequent, mount of this sb + * + * Returns: 0 or -ve on error + */ + +static int gfs2_get_sb(struct file_system_type *fs_type, int flags, +		       const char *dev_name, void *data, struct vfsmount *mnt) +{ +	struct block_device *bdev; +	struct super_block *s; +	fmode_t mode = FMODE_READ; +	int error; +	struct gfs2_args args; +	struct gfs2_sbd *sdp; + +	if (!(flags & MS_RDONLY)) +		mode |= FMODE_WRITE; + +	bdev = open_bdev_exclusive(dev_name, mode, fs_type); +	if (IS_ERR(bdev)) +		return PTR_ERR(bdev); + +	/* +	 * once the super is inserted into the list by sget, s_umount +	 * will protect the lockfs code from trying to start a snapshot +	 * while we are mounting +	 */ +	mutex_lock(&bdev->bd_fsfreeze_mutex); +	if (bdev->bd_fsfreeze_count > 0) { +		mutex_unlock(&bdev->bd_fsfreeze_mutex); +		error = -EBUSY; +		goto error_bdev; +	} +	s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev); +	mutex_unlock(&bdev->bd_fsfreeze_mutex); +	error = PTR_ERR(s); +	if (IS_ERR(s)) +		goto error_bdev; + +	memset(&args, 0, sizeof(args)); +	args.ar_quota = GFS2_QUOTA_DEFAULT; +	args.ar_data = GFS2_DATA_DEFAULT; +	args.ar_commit = 60; +	args.ar_statfs_quantum = 30; +	args.ar_quota_quantum = 60; +	args.ar_errors = GFS2_ERRORS_DEFAULT; + +	error = gfs2_mount_args(&args, data); +	if (error) { +		printk(KERN_WARNING "GFS2: can't parse mount arguments\n"); +		if (s->s_root) +			goto error_super; +		deactivate_locked_super(s); +		return error; +	} + +	if (s->s_root) { +		error = -EBUSY; +		if ((flags ^ s->s_flags) & MS_RDONLY) +			goto error_super; +		close_bdev_exclusive(bdev, mode); +	} else { +		char b[BDEVNAME_SIZE]; + +		s->s_flags = flags; +		s->s_mode = mode; +		strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); +		sb_set_blocksize(s, block_size(bdev)); +		error = fill_super(s, &args, flags & MS_SILENT ? 1 : 0); +		if (error) { +			deactivate_locked_super(s); +			return error; +		} +		s->s_flags |= MS_ACTIVE; +		bdev->bd_super = s; +	} + +	sdp = s->s_fs_info; +	mnt->mnt_sb = s; +	if (args.ar_meta) +		mnt->mnt_root = dget(sdp->sd_master_dir); +	else +		mnt->mnt_root = dget(sdp->sd_root_dir); +	return 0; + +error_super: +	deactivate_locked_super(s); +error_bdev: +	close_bdev_exclusive(bdev, mode); +	return error; +} +  static int set_meta_super(struct super_block *s, void *ptr)  {  	return -EINVAL; @@ -1274,13 +1384,17 @@ static int gfs2_get_sb_meta(struct file_system_type *fs_type, int flags,  		       dev_name, error);  		return error;  	} -	s = sget(&gfs2_fs_type, test_meta_super, set_meta_super, +	s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super,  		 path.dentry->d_inode->i_sb->s_bdev);  	path_put(&path);  	if (IS_ERR(s)) {  		printk(KERN_WARNING "GFS2: gfs2 mount does not exist\n");  		return PTR_ERR(s);  	} +	if ((flags ^ s->s_flags) & MS_RDONLY) { +		deactivate_locked_super(s); +		return -EBUSY; +	}  	sdp = s->s_fs_info;  	mnt->mnt_sb = s;  	mnt->mnt_root = dget(sdp->sd_master_dir); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 2e9b9326bfc..e3bf6eab875 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -15,7 +15,7 @@   * fuzziness in the current usage value of IDs that are being used on different   * nodes in the cluster simultaneously.  So, it is possible for a user on   * multiple nodes to overrun their quota, but that overrun is controlable. - * Since quota tags are part of transactions, there is no need to a quota check + * Since quota tags are part of transactions, there is no need for a quota check   * program to be run on node crashes or anything like that.   *   * There are couple of knobs that let the administrator manage the quota @@ -47,6 +47,8 @@  #include <linux/gfs2_ondisk.h>  #include <linux/kthread.h>  #include <linux/freezer.h> +#include <linux/quota.h> +#include <linux/dqblk_xfs.h>  #include "gfs2.h"  #include "incore.h" @@ -65,13 +67,6 @@  #define QUOTA_USER 1  #define QUOTA_GROUP 0 -struct gfs2_quota_host { -	u64 qu_limit; -	u64 qu_warn; -	s64 qu_value; -	u32 qu_ll_next; -}; -  struct gfs2_quota_change_host {  	u64 qc_change;  	u32 qc_flags; /* GFS2_QCF_... */ @@ -164,7 +159,7 @@ fail:  	return error;  } -static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create, +static int qd_get(struct gfs2_sbd *sdp, int user, u32 id,  		  struct gfs2_quota_data **qdp)  {  	struct gfs2_quota_data *qd = NULL, *new_qd = NULL; @@ -202,7 +197,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, int create,  		spin_unlock(&qd_lru_lock); -		if (qd || !create) { +		if (qd) {  			if (new_qd) {  				gfs2_glock_put(new_qd->qd_gl);  				kmem_cache_free(gfs2_quotad_cachep, new_qd); @@ -461,12 +456,12 @@ static void qd_unlock(struct gfs2_quota_data *qd)  	qd_put(qd);  } -static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id, int create, +static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id,  		    struct gfs2_quota_data **qdp)  {  	int error; -	error = qd_get(sdp, user, id, create, qdp); +	error = qd_get(sdp, user, id, qdp);  	if (error)  		return error; @@ -508,20 +503,20 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)  	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)  		return 0; -	error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, CREATE, qd); +	error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd);  	if (error)  		goto out;  	al->al_qd_num++;  	qd++; -	error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, CREATE, qd); +	error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd);  	if (error)  		goto out;  	al->al_qd_num++;  	qd++;  	if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { -		error = qdsb_get(sdp, QUOTA_USER, uid, CREATE, qd); +		error = qdsb_get(sdp, QUOTA_USER, uid, qd);  		if (error)  			goto out;  		al->al_qd_num++; @@ -529,7 +524,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)  	}  	if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { -		error = qdsb_get(sdp, QUOTA_GROUP, gid, CREATE, qd); +		error = qdsb_get(sdp, QUOTA_GROUP, gid, qd);  		if (error)  			goto out;  		al->al_qd_num++; @@ -617,48 +612,36 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)  	mutex_unlock(&sdp->sd_quota_mutex);  } -static void gfs2_quota_in(struct gfs2_quota_host *qu, const void *buf) -{ -	const struct gfs2_quota *str = buf; - -	qu->qu_limit = be64_to_cpu(str->qu_limit); -	qu->qu_warn = be64_to_cpu(str->qu_warn); -	qu->qu_value = be64_to_cpu(str->qu_value); -	qu->qu_ll_next = be32_to_cpu(str->qu_ll_next); -} - -static void gfs2_quota_out(const struct gfs2_quota_host *qu, void *buf) -{ -	struct gfs2_quota *str = buf; - -	str->qu_limit = cpu_to_be64(qu->qu_limit); -	str->qu_warn = cpu_to_be64(qu->qu_warn); -	str->qu_value = cpu_to_be64(qu->qu_value); -	str->qu_ll_next = cpu_to_be32(qu->qu_ll_next); -	memset(&str->qu_reserved, 0, sizeof(str->qu_reserved)); -} -  /** - * gfs2_adjust_quota + * gfs2_adjust_quota - adjust record of current block usage + * @ip: The quota inode + * @loc: Offset of the entry in the quota file + * @change: The amount of usage change to record + * @qd: The quota data + * @fdq: The updated limits to record   *   * This function was mostly borrowed from gfs2_block_truncate_page which was   * in turn mostly borrowed from ext3 + * + * Returns: 0 or -ve on error   */ +  static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, -			     s64 change, struct gfs2_quota_data *qd) +			     s64 change, struct gfs2_quota_data *qd, +			     struct fs_disk_quota *fdq)  {  	struct inode *inode = &ip->i_inode;  	struct address_space *mapping = inode->i_mapping;  	unsigned long index = loc >> PAGE_CACHE_SHIFT;  	unsigned offset = loc & (PAGE_CACHE_SIZE - 1);  	unsigned blocksize, iblock, pos; -	struct buffer_head *bh; +	struct buffer_head *bh, *dibh;  	struct page *page;  	void *kaddr; -	char *ptr; -	struct gfs2_quota_host qp; +	struct gfs2_quota *qp;  	s64 value;  	int err = -EIO; +	u64 size;  	if (gfs2_is_stuffed(ip))  		gfs2_unstuff_dinode(ip, NULL); @@ -700,18 +683,38 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,  	gfs2_trans_add_bh(ip->i_gl, bh, 0);  	kaddr = kmap_atomic(page, KM_USER0); -	ptr = kaddr + offset; -	gfs2_quota_in(&qp, ptr); -	qp.qu_value += change; -	value = qp.qu_value; -	gfs2_quota_out(&qp, ptr); +	qp = kaddr + offset; +	value = (s64)be64_to_cpu(qp->qu_value) + change; +	qp->qu_value = cpu_to_be64(value); +	qd->qd_qb.qb_value = qp->qu_value; +	if (fdq) { +		if (fdq->d_fieldmask & FS_DQ_BSOFT) { +			qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit); +			qd->qd_qb.qb_warn = qp->qu_warn; +		} +		if (fdq->d_fieldmask & FS_DQ_BHARD) { +			qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit); +			qd->qd_qb.qb_limit = qp->qu_limit; +		} +	}  	flush_dcache_page(page);  	kunmap_atomic(kaddr, KM_USER0); -	err = 0; -	qd->qd_qb.qb_magic = cpu_to_be32(GFS2_MAGIC); -	qd->qd_qb.qb_value = cpu_to_be64(value); -	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_magic = cpu_to_be32(GFS2_MAGIC); -	((struct gfs2_quota_lvb*)(qd->qd_gl->gl_lvb))->qb_value = cpu_to_be64(value); + +	err = gfs2_meta_inode_buffer(ip, &dibh); +	if (err) +		goto unlock; + +	size = loc + sizeof(struct gfs2_quota); +	if (size > inode->i_size) { +		ip->i_disksize = size; +		i_size_write(inode, size); +	} +	inode->i_mtime = inode->i_atime = CURRENT_TIME; +	gfs2_trans_add_bh(ip->i_gl, dibh, 1); +	gfs2_dinode_out(ip, dibh->b_data); +	brelse(dibh); +	mark_inode_dirty(inode); +  unlock:  	unlock_page(page);  	page_cache_release(page); @@ -739,9 +742,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)  		return -ENOMEM;  	sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL); +	mutex_lock_nested(&ip->i_inode.i_mutex, I_MUTEX_QUOTA);  	for (qx = 0; qx < num_qd; qx++) { -		error = gfs2_glock_nq_init(qda[qx]->qd_gl, -					   LM_ST_EXCLUSIVE, +		error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE,  					   GL_NOCACHE, &ghs[qx]);  		if (error)  			goto out; @@ -795,9 +798,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)  	for (x = 0; x < num_qd; x++) {  		qd = qda[x];  		offset = qd2offset(qd); -		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, -					  (struct gfs2_quota_data *) -					  qd); +		error = gfs2_adjust_quota(ip, offset, qd->qd_change_sync, qd, NULL);  		if (error)  			goto out_end_trans; @@ -817,21 +818,44 @@ out_gunlock:  out:  	while (qx--)  		gfs2_glock_dq_uninit(&ghs[qx]); +	mutex_unlock(&ip->i_inode.i_mutex);  	kfree(ghs);  	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);  	return error;  } +static int update_qd(struct gfs2_sbd *sdp, struct gfs2_quota_data *qd) +{ +	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); +	struct gfs2_quota q; +	struct gfs2_quota_lvb *qlvb; +	loff_t pos; +	int error; + +	memset(&q, 0, sizeof(struct gfs2_quota)); +	pos = qd2offset(qd); +	error = gfs2_internal_read(ip, NULL, (char *)&q, &pos, sizeof(q)); +	if (error < 0) +		return error; + +	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; +	qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC); +	qlvb->__pad = 0; +	qlvb->qb_limit = q.qu_limit; +	qlvb->qb_warn = q.qu_warn; +	qlvb->qb_value = q.qu_value; +	qd->qd_qb = *qlvb; + +	return 0; +} +  static int do_glock(struct gfs2_quota_data *qd, int force_refresh,  		    struct gfs2_holder *q_gh)  {  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd;  	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);  	struct gfs2_holder i_gh; -	struct gfs2_quota_host q; -	char buf[sizeof(struct gfs2_quota)];  	int error; -	struct gfs2_quota_lvb *qlvb;  restart:  	error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_SHARED, 0, q_gh); @@ -841,11 +865,9 @@ restart:  	qd->qd_qb = *(struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;  	if (force_refresh || qd->qd_qb.qb_magic != cpu_to_be32(GFS2_MAGIC)) { -		loff_t pos;  		gfs2_glock_dq_uninit(q_gh); -		error = gfs2_glock_nq_init(qd->qd_gl, -					   LM_ST_EXCLUSIVE, GL_NOCACHE, -					   q_gh); +		error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, +					   GL_NOCACHE, q_gh);  		if (error)  			return error; @@ -853,29 +875,14 @@ restart:  		if (error)  			goto fail; -		memset(buf, 0, sizeof(struct gfs2_quota)); -		pos = qd2offset(qd); -		error = gfs2_internal_read(ip, NULL, buf, &pos, -					   sizeof(struct gfs2_quota)); -		if (error < 0) +		error = update_qd(sdp, qd); +		if (error)  			goto fail_gunlock;  		gfs2_glock_dq_uninit(&i_gh); - -		gfs2_quota_in(&q, buf); -		qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; -		qlvb->qb_magic = cpu_to_be32(GFS2_MAGIC); -		qlvb->__pad = 0; -		qlvb->qb_limit = cpu_to_be64(q.qu_limit); -		qlvb->qb_warn = cpu_to_be64(q.qu_warn); -		qlvb->qb_value = cpu_to_be64(q.qu_value); -		qd->qd_qb = *qlvb; - -		if (gfs2_glock_is_blocking(qd->qd_gl)) { -			gfs2_glock_dq_uninit(q_gh); -			force_refresh = 0; -			goto restart; -		} +		gfs2_glock_dq_uninit(q_gh); +		force_refresh = 0; +		goto restart;  	}  	return 0; @@ -995,7 +1002,7 @@ static int print_message(struct gfs2_quota_data *qd, char *type)  {  	struct gfs2_sbd *sdp = qd->qd_gl->gl_sbd; -	printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\r\n", +	printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n",  	       sdp->sd_fsname, type,  	       (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group",  	       qd->qd_id); @@ -1032,6 +1039,10 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)  		if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) {  			print_message(qd, "exceeded"); +			quota_send_warning(test_bit(QDF_USER, &qd->qd_flags) ? +					   USRQUOTA : GRPQUOTA, qd->qd_id, +					   sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN); +  			error = -EDQUOT;  			break;  		} else if (be64_to_cpu(qd->qd_qb.qb_warn) && @@ -1039,6 +1050,9 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid)  			   time_after_eq(jiffies, qd->qd_last_warn +  					 gfs2_tune_get(sdp,  						gt_quota_warn_period) * HZ)) { +			quota_send_warning(test_bit(QDF_USER, &qd->qd_flags) ? +					   USRQUOTA : GRPQUOTA, qd->qd_id, +					   sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN);  			error = print_message(qd, "warning");  			qd->qd_last_warn = jiffies;  		} @@ -1069,8 +1083,9 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,  	}  } -int gfs2_quota_sync(struct gfs2_sbd *sdp) +int gfs2_quota_sync(struct super_block *sb, int type)  { +	struct gfs2_sbd *sdp = sb->s_fs_info;  	struct gfs2_quota_data **qda;  	unsigned int max_qd = gfs2_tune_get(sdp, gt_quota_simul_sync);  	unsigned int num_qd; @@ -1118,7 +1133,7 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)  	struct gfs2_holder q_gh;  	int error; -	error = qd_get(sdp, user, id, CREATE, &qd); +	error = qd_get(sdp, user, id, &qd);  	if (error)  		return error; @@ -1127,7 +1142,6 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)  		gfs2_glock_dq_uninit(&q_gh);  	qd_put(qd); -  	return error;  } @@ -1298,12 +1312,12 @@ static void quotad_error(struct gfs2_sbd *sdp, const char *msg, int error)  }  static void quotad_check_timeo(struct gfs2_sbd *sdp, const char *msg, -			       int (*fxn)(struct gfs2_sbd *sdp), +			       int (*fxn)(struct super_block *sb, int type),  			       unsigned long t, unsigned long *timeo,  			       unsigned int *new_timeo)  {  	if (t >= *timeo) { -		int error = fxn(sdp); +		int error = fxn(sdp->sd_vfs, 0);  		quotad_error(sdp, msg, error);  		*timeo = gfs2_tune_get_i(&sdp->sd_tune, new_timeo) * HZ;  	} else { @@ -1330,6 +1344,14 @@ static void quotad_check_trunc_list(struct gfs2_sbd *sdp)  	}  } +void gfs2_wake_up_statfs(struct gfs2_sbd *sdp) { +	if (!sdp->sd_statfs_force_sync) { +		sdp->sd_statfs_force_sync = 1; +		wake_up(&sdp->sd_quota_wait); +	} +} + +  /**   * gfs2_quotad - Write cached quota changes into the quota file   * @sdp: Pointer to GFS2 superblock @@ -1349,8 +1371,15 @@ int gfs2_quotad(void *data)  	while (!kthread_should_stop()) {  		/* Update the master statfs file */ -		quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t, -				   &statfs_timeo, &tune->gt_statfs_quantum); +		if (sdp->sd_statfs_force_sync) { +			int error = gfs2_statfs_sync(sdp->sd_vfs, 0); +			quotad_error(sdp, "statfs", error); +			statfs_timeo = gfs2_tune_get(sdp, gt_statfs_quantum) * HZ; +		} +		else +			quotad_check_timeo(sdp, "statfs", gfs2_statfs_sync, t, +				   	   &statfs_timeo, +					   &tune->gt_statfs_quantum);  		/* Update quota file */  		quotad_check_timeo(sdp, "sync", gfs2_quota_sync, t, @@ -1367,7 +1396,7 @@ int gfs2_quotad(void *data)  		spin_lock(&sdp->sd_trunc_lock);  		empty = list_empty(&sdp->sd_trunc_list);  		spin_unlock(&sdp->sd_trunc_lock); -		if (empty) +		if (empty && !sdp->sd_statfs_force_sync)  			t -= schedule_timeout(t);  		else  			t = 0; @@ -1377,3 +1406,181 @@ int gfs2_quotad(void *data)  	return 0;  } +static int gfs2_quota_get_xstate(struct super_block *sb, +				 struct fs_quota_stat *fqs) +{ +	struct gfs2_sbd *sdp = sb->s_fs_info; + +	memset(fqs, 0, sizeof(struct fs_quota_stat)); +	fqs->qs_version = FS_QSTAT_VERSION; +	if (sdp->sd_args.ar_quota == GFS2_QUOTA_ON) +		fqs->qs_flags = (XFS_QUOTA_UDQ_ENFD | XFS_QUOTA_GDQ_ENFD); +	else if (sdp->sd_args.ar_quota == GFS2_QUOTA_ACCOUNT) +		fqs->qs_flags = (XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_GDQ_ACCT); +	if (sdp->sd_quota_inode) { +		fqs->qs_uquota.qfs_ino = GFS2_I(sdp->sd_quota_inode)->i_no_addr; +		fqs->qs_uquota.qfs_nblks = sdp->sd_quota_inode->i_blocks; +	} +	fqs->qs_uquota.qfs_nextents = 1; /* unsupported */ +	fqs->qs_gquota = fqs->qs_uquota; /* its the same inode in both cases */ +	fqs->qs_incoredqs = atomic_read(&qd_lru_count); +	return 0; +} + +static int gfs2_xquota_get(struct super_block *sb, int type, qid_t id, +			   struct fs_disk_quota *fdq) +{ +	struct gfs2_sbd *sdp = sb->s_fs_info; +	struct gfs2_quota_lvb *qlvb; +	struct gfs2_quota_data *qd; +	struct gfs2_holder q_gh; +	int error; + +	memset(fdq, 0, sizeof(struct fs_disk_quota)); + +	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) +		return -ESRCH; /* Crazy XFS error code */ + +	if (type == USRQUOTA) +		type = QUOTA_USER; +	else if (type == GRPQUOTA) +		type = QUOTA_GROUP; +	else +		return -EINVAL; + +	error = qd_get(sdp, type, id, &qd); +	if (error) +		return error; +	error = do_glock(qd, FORCE, &q_gh); +	if (error) +		goto out; + +	qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; +	fdq->d_version = FS_DQUOT_VERSION; +	fdq->d_flags = (type == QUOTA_USER) ? XFS_USER_QUOTA : XFS_GROUP_QUOTA; +	fdq->d_id = id; +	fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit); +	fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn); +	fdq->d_bcount = be64_to_cpu(qlvb->qb_value); + +	gfs2_glock_dq_uninit(&q_gh); +out: +	qd_put(qd); +	return error; +} + +/* GFS2 only supports a subset of the XFS fields */ +#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD) + +static int gfs2_xquota_set(struct super_block *sb, int type, qid_t id, +			   struct fs_disk_quota *fdq) +{ +	struct gfs2_sbd *sdp = sb->s_fs_info; +	struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); +	struct gfs2_quota_data *qd; +	struct gfs2_holder q_gh, i_gh; +	unsigned int data_blocks, ind_blocks; +	unsigned int blocks = 0; +	int alloc_required; +	struct gfs2_alloc *al; +	loff_t offset; +	int error; + +	if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) +		return -ESRCH; /* Crazy XFS error code */ + +	switch(type) { +	case USRQUOTA: +		type = QUOTA_USER; +		if (fdq->d_flags != XFS_USER_QUOTA) +			return -EINVAL; +		break; +	case GRPQUOTA: +		type = QUOTA_GROUP; +		if (fdq->d_flags != XFS_GROUP_QUOTA) +			return -EINVAL; +		break; +	default: +		return -EINVAL; +	} + +	if (fdq->d_fieldmask & ~GFS2_FIELDMASK) +		return -EINVAL; +	if (fdq->d_id != id) +		return -EINVAL; + +	error = qd_get(sdp, type, id, &qd); +	if (error) +		return error; + +	mutex_lock(&ip->i_inode.i_mutex); +	error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh); +	if (error) +		goto out_put; +	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); +	if (error) +		goto out_q; + +	/* Check for existing entry, if none then alloc new blocks */ +	error = update_qd(sdp, qd); +	if (error) +		goto out_i; + +	/* If nothing has changed, this is a no-op */ +	if ((fdq->d_fieldmask & FS_DQ_BSOFT) && +	    (fdq->d_blk_softlimit == be64_to_cpu(qd->qd_qb.qb_warn))) +		fdq->d_fieldmask ^= FS_DQ_BSOFT; +	if ((fdq->d_fieldmask & FS_DQ_BHARD) && +	    (fdq->d_blk_hardlimit == be64_to_cpu(qd->qd_qb.qb_limit))) +		fdq->d_fieldmask ^= FS_DQ_BHARD; +	if (fdq->d_fieldmask == 0) +		goto out_i; + +	offset = qd2offset(qd); +	error = gfs2_write_alloc_required(ip, offset, sizeof(struct gfs2_quota), +					  &alloc_required); +	if (error) +		goto out_i; +	if (alloc_required) { +		al = gfs2_alloc_get(ip); +		if (al == NULL) +			goto out_i; +		gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota), +				       &data_blocks, &ind_blocks); +		blocks = al->al_requested = 1 + data_blocks + ind_blocks; +		error = gfs2_inplace_reserve(ip); +		if (error) +			goto out_alloc; +	} + +	error = gfs2_trans_begin(sdp, blocks + RES_DINODE + 1, 0); +	if (error) +		goto out_release; + +	/* Apply changes */ +	error = gfs2_adjust_quota(ip, offset, 0, qd, fdq); + +	gfs2_trans_end(sdp); +out_release: +	if (alloc_required) { +		gfs2_inplace_release(ip); +out_alloc: +		gfs2_alloc_put(ip); +	} +out_i: +	gfs2_glock_dq_uninit(&i_gh); +out_q: +	gfs2_glock_dq_uninit(&q_gh); +out_put: +	mutex_unlock(&ip->i_inode.i_mutex); +	qd_put(qd); +	return error; +} + +const struct quotactl_ops gfs2_quotactl_ops = { +	.quota_sync     = gfs2_quota_sync, +	.get_xstate     = gfs2_quota_get_xstate, +	.get_xquota	= gfs2_xquota_get, +	.set_xquota	= gfs2_xquota_set, +}; + diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index 0fa5fa63d0e..e271fa07ad0 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h @@ -25,13 +25,15 @@ extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);  extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,  			      u32 uid, u32 gid); -extern int gfs2_quota_sync(struct gfs2_sbd *sdp); +extern int gfs2_quota_sync(struct super_block *sb, int type);  extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);  extern int gfs2_quota_init(struct gfs2_sbd *sdp);  extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp);  extern int gfs2_quotad(void *data); +extern void gfs2_wake_up_statfs(struct gfs2_sbd *sdp); +  static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)  {  	struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); @@ -50,5 +52,6 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip)  }  extern int gfs2_shrink_qd_memory(int nr, gfp_t gfp_mask); +extern const struct quotactl_ops gfs2_quotactl_ops;  #endif /* __QUOTA_DOT_H__ */ diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 09fa3196557..4b9bece3d43 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -410,7 +410,9 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea  	memset(lh, 0, sizeof(struct gfs2_log_header));  	lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);  	lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH); +	lh->lh_header.__pad0 = cpu_to_be64(0);  	lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH); +	lh->lh_header.mh_jid = cpu_to_be32(sdp->sd_jdesc->jd_jid);  	lh->lh_sequence = cpu_to_be64(head->lh_sequence + 1);  	lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT);  	lh->lh_blkno = cpu_to_be32(lblock); diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 8f1cfb02a6c..0608f490c29 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1710,11 +1710,16 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)  {  	struct gfs2_rgrpd *rgd;  	struct gfs2_holder ri_gh, rgd_gh; +	struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex); +	int ri_locked = 0;  	int error; -	error = gfs2_rindex_hold(sdp, &ri_gh); -	if (error) -		goto fail; +	if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { +		error = gfs2_rindex_hold(sdp, &ri_gh); +		if (error) +			goto fail; +		ri_locked = 1; +	}  	error = -EINVAL;  	rgd = gfs2_blk2rgrpd(sdp, no_addr); @@ -1730,7 +1735,8 @@ int gfs2_check_blk_type(struct gfs2_sbd *sdp, u64 no_addr, unsigned int type)  	gfs2_glock_dq_uninit(&rgd_gh);  fail_rindex: -	gfs2_glock_dq_uninit(&ri_gh); +	if (ri_locked) +		gfs2_glock_dq_uninit(&ri_gh);  fail:  	return error;  } diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 0ec3ec672de..c282ad41f3d 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -70,6 +70,11 @@ enum {  	Opt_commit,  	Opt_err_withdraw,  	Opt_err_panic, +	Opt_statfs_quantum, +	Opt_statfs_percent, +	Opt_quota_quantum, +	Opt_barrier, +	Opt_nobarrier,  	Opt_error,  }; @@ -101,18 +106,23 @@ static const match_table_t tokens = {  	{Opt_commit, "commit=%d"},  	{Opt_err_withdraw, "errors=withdraw"},  	{Opt_err_panic, "errors=panic"}, +	{Opt_statfs_quantum, "statfs_quantum=%d"}, +	{Opt_statfs_percent, "statfs_percent=%d"}, +	{Opt_quota_quantum, "quota_quantum=%d"}, +	{Opt_barrier, "barrier"}, +	{Opt_nobarrier, "nobarrier"},  	{Opt_error, NULL}  };  /**   * gfs2_mount_args - Parse mount options - * @sdp: - * @data: + * @args: The structure into which the parsed options will be written + * @options: The options to parse   *   * Return: errno   */ -int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options) +int gfs2_mount_args(struct gfs2_args *args, char *options)  {  	char *o;  	int token; @@ -157,7 +167,7 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options)  			break;  		case Opt_debug:  			if (args->ar_errors == GFS2_ERRORS_PANIC) { -				fs_info(sdp, "-o debug and -o errors=panic " +				printk(KERN_WARNING "GFS2: -o debug and -o errors=panic "  				       "are mutually exclusive.\n");  				return -EINVAL;  			} @@ -210,7 +220,29 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options)  		case Opt_commit:  			rv = match_int(&tmp[0], &args->ar_commit);  			if (rv || args->ar_commit <= 0) { -				fs_info(sdp, "commit mount option requires a positive numeric argument\n"); +				printk(KERN_WARNING "GFS2: commit mount option requires a positive numeric argument\n"); +				return rv ? rv : -EINVAL; +			} +			break; +		case Opt_statfs_quantum: +			rv = match_int(&tmp[0], &args->ar_statfs_quantum); +			if (rv || args->ar_statfs_quantum < 0) { +				printk(KERN_WARNING "GFS2: statfs_quantum mount option requires a non-negative numeric argument\n"); +				return rv ? rv : -EINVAL; +			} +			break; +		case Opt_quota_quantum: +			rv = match_int(&tmp[0], &args->ar_quota_quantum); +			if (rv || args->ar_quota_quantum <= 0) { +				printk(KERN_WARNING "GFS2: quota_quantum mount option requires a positive numeric argument\n"); +				return rv ? rv : -EINVAL; +			} +			break; +		case Opt_statfs_percent: +			rv = match_int(&tmp[0], &args->ar_statfs_percent); +			if (rv || args->ar_statfs_percent < 0 || +			    args->ar_statfs_percent > 100) { +				printk(KERN_WARNING "statfs_percent mount option requires a numeric argument between 0 and 100\n");  				return rv ? rv : -EINVAL;  			}  			break; @@ -219,15 +251,21 @@ int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *options)  			break;  		case Opt_err_panic:  			if (args->ar_debug) { -				fs_info(sdp, "-o debug and -o errors=panic " +				printk(KERN_WARNING "GFS2: -o debug and -o errors=panic "  					"are mutually exclusive.\n");  				return -EINVAL;  			}  			args->ar_errors = GFS2_ERRORS_PANIC;  			break; +		case Opt_barrier: +			args->ar_nobarrier = 0; +			break; +		case Opt_nobarrier: +			args->ar_nobarrier = 1; +			break;  		case Opt_error:  		default: -			fs_info(sdp, "invalid mount option: %s\n", o); +			printk(KERN_WARNING "GFS2: invalid mount option: %s\n", o);  			return -EINVAL;  		}  	} @@ -442,7 +480,10 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,  {  	struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);  	struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; +	struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master;  	struct buffer_head *l_bh; +	s64 x, y; +	int need_sync = 0;  	int error;  	error = gfs2_meta_inode_buffer(l_ip, &l_bh); @@ -456,9 +497,17 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free,  	l_sc->sc_free += free;  	l_sc->sc_dinodes += dinodes;  	gfs2_statfs_change_out(l_sc, l_bh->b_data + sizeof(struct gfs2_dinode)); +	if (sdp->sd_args.ar_statfs_percent) { +		x = 100 * l_sc->sc_free; +		y = m_sc->sc_free * sdp->sd_args.ar_statfs_percent; +		if (x >= y || x <= -y) +			need_sync = 1; +	}  	spin_unlock(&sdp->sd_statfs_spin);  	brelse(l_bh); +	if (need_sync) +		gfs2_wake_up_statfs(sdp);  }  void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh, @@ -484,8 +533,9 @@ void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,  	gfs2_statfs_change_out(m_sc, m_bh->b_data + sizeof(struct gfs2_dinode));  } -int gfs2_statfs_sync(struct gfs2_sbd *sdp) +int gfs2_statfs_sync(struct super_block *sb, int type)  { +	struct gfs2_sbd *sdp = sb->s_fs_info;  	struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode);  	struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode);  	struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; @@ -521,6 +571,7 @@ int gfs2_statfs_sync(struct gfs2_sbd *sdp)  		goto out_bh2;  	update_statfs(sdp, m_bh, l_bh); +	sdp->sd_statfs_force_sync = 0;  	gfs2_trans_end(sdp); @@ -712,8 +763,8 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)  	int error;  	flush_workqueue(gfs2_delete_workqueue); -	gfs2_quota_sync(sdp); -	gfs2_statfs_sync(sdp); +	gfs2_quota_sync(sdp->sd_vfs, 0); +	gfs2_statfs_sync(sdp->sd_vfs, 0);  	error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,  				   &t_gh); @@ -1061,8 +1112,13 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)  	spin_lock(>->gt_spin);  	args.ar_commit = gt->gt_log_flush_secs; +	args.ar_quota_quantum = gt->gt_quota_quantum; +	if (gt->gt_statfs_slow) +		args.ar_statfs_quantum = 0; +	else +		args.ar_statfs_quantum = gt->gt_statfs_quantum;  	spin_unlock(>->gt_spin); -	error = gfs2_mount_args(sdp, &args, data); +	error = gfs2_mount_args(&args, data);  	if (error)  		return error; @@ -1097,8 +1153,21 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)  		sb->s_flags |= MS_POSIXACL;  	else  		sb->s_flags &= ~MS_POSIXACL; +	if (sdp->sd_args.ar_nobarrier) +		set_bit(SDF_NOBARRIERS, &sdp->sd_flags); +	else +		clear_bit(SDF_NOBARRIERS, &sdp->sd_flags);  	spin_lock(>->gt_spin);  	gt->gt_log_flush_secs = args.ar_commit; +	gt->gt_quota_quantum = args.ar_quota_quantum; +	if (args.ar_statfs_quantum) { +		gt->gt_statfs_slow = 0; +		gt->gt_statfs_quantum = args.ar_statfs_quantum; +	} +	else { +		gt->gt_statfs_slow = 1; +		gt->gt_statfs_quantum = 30; +	}  	spin_unlock(>->gt_spin);  	gfs2_online_uevent(sdp); @@ -1179,7 +1248,7 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)  {  	struct gfs2_sbd *sdp = mnt->mnt_sb->s_fs_info;  	struct gfs2_args *args = &sdp->sd_args; -	int lfsecs; +	int val;  	if (is_ancestor(mnt->mnt_root, sdp->sd_master_dir))  		seq_printf(s, ",meta"); @@ -1240,9 +1309,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)  	}  	if (args->ar_discard)  		seq_printf(s, ",discard"); -	lfsecs = sdp->sd_tune.gt_log_flush_secs; -	if (lfsecs != 60) -		seq_printf(s, ",commit=%d", lfsecs); +	val = sdp->sd_tune.gt_log_flush_secs; +	if (val != 60) +		seq_printf(s, ",commit=%d", val); +	val = sdp->sd_tune.gt_statfs_quantum; +	if (val != 30) +		seq_printf(s, ",statfs_quantum=%d", val); +	val = sdp->sd_tune.gt_quota_quantum; +	if (val != 60) +		seq_printf(s, ",quota_quantum=%d", val); +	if (args->ar_statfs_percent) +		seq_printf(s, ",statfs_percent=%d", args->ar_statfs_percent);  	if (args->ar_errors != GFS2_ERRORS_DEFAULT) {  		const char *state; @@ -1259,6 +1336,9 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)  		}  		seq_printf(s, ",errors=%s", state);  	} +	if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) +		seq_printf(s, ",nobarrier"); +  	return 0;  } diff --git a/fs/gfs2/super.h b/fs/gfs2/super.h index 235db368288..3df60f2d84e 100644 --- a/fs/gfs2/super.h +++ b/fs/gfs2/super.h @@ -27,7 +27,7 @@ static inline unsigned int gfs2_jindex_size(struct gfs2_sbd *sdp)  extern void gfs2_jindex_free(struct gfs2_sbd *sdp); -extern int gfs2_mount_args(struct gfs2_sbd *sdp, struct gfs2_args *args, char *data); +extern int gfs2_mount_args(struct gfs2_args *args, char *data);  extern struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid);  extern int gfs2_jdesc_check(struct gfs2_jdesc *jd); @@ -44,7 +44,7 @@ extern void gfs2_statfs_change_in(struct gfs2_statfs_change_host *sc,  				  const void *buf);  extern void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh,  			  struct buffer_head *l_bh); -extern int gfs2_statfs_sync(struct gfs2_sbd *sdp); +extern int gfs2_statfs_sync(struct super_block *sb, int type);  extern int gfs2_freeze_fs(struct gfs2_sbd *sdp);  extern void gfs2_unfreeze_fs(struct gfs2_sbd *sdp); diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 446329728d5..c5dad1eb7b9 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -158,7 +158,7 @@ static ssize_t statfs_sync_store(struct gfs2_sbd *sdp, const char *buf,  	if (simple_strtol(buf, NULL, 0) != 1)  		return -EINVAL; -	gfs2_statfs_sync(sdp); +	gfs2_statfs_sync(sdp->sd_vfs, 0);  	return len;  } @@ -171,13 +171,14 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,  	if (simple_strtol(buf, NULL, 0) != 1)  		return -EINVAL; -	gfs2_quota_sync(sdp); +	gfs2_quota_sync(sdp->sd_vfs, 0);  	return len;  }  static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,  					size_t len)  { +	int error;  	u32 id;  	if (!capable(CAP_SYS_ADMIN)) @@ -185,13 +186,14 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf,  	id = simple_strtoul(buf, NULL, 0); -	gfs2_quota_refresh(sdp, 1, id); -	return len; +	error = gfs2_quota_refresh(sdp, 1, id); +	return error ? error : len;  }  static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,  					 size_t len)  { +	int error;  	u32 id;  	if (!capable(CAP_SYS_ADMIN)) @@ -199,8 +201,8 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf,  	id = simple_strtoul(buf, NULL, 0); -	gfs2_quota_refresh(sdp, 0, id); -	return len; +	error = gfs2_quota_refresh(sdp, 0, id); +	return error ? error : len;  }  static ssize_t demote_rq_store(struct gfs2_sbd *sdp, const char *buf, size_t len) diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 8a0f8ef6ee2..912f5cbc474 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -186,8 +186,8 @@ static int ea_find_i(struct gfs2_inode *ip, struct buffer_head *bh,  	return 0;  } -int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, -		 struct gfs2_ea_location *el) +static int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, +			struct gfs2_ea_location *el)  {  	struct ea_find ef;  	int error; @@ -516,8 +516,8 @@ out:  	return error;  } -int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, -		     char *data, size_t size) +static int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, +			    char *data, size_t size)  {  	int ret;  	size_t len = GFS2_EA_DATA_LEN(el->el_ea); @@ -534,6 +534,36 @@ int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el,  	return len;  } +int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **ppdata) +{ +	struct gfs2_ea_location el; +	int error; +	int len; +	char *data; + +	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, name, &el); +	if (error) +		return error; +	if (!el.el_ea) +		goto out; +	if (!GFS2_EA_DATA_LEN(el.el_ea)) +		goto out; + +	len = GFS2_EA_DATA_LEN(el.el_ea); +	data = kmalloc(len, GFP_NOFS); +	error = -ENOMEM; +	if (data == NULL) +		goto out; + +	error = gfs2_ea_get_copy(ip, &el, data, len); +	if (error == 0) +		error = len; +	*ppdata = data; +out: +	brelse(el.el_bh); +	return error; +} +  /**   * gfs2_xattr_get - Get a GFS2 extended attribute   * @inode: The inode @@ -1259,22 +1289,26 @@ fail:  	return error;  } -int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, -		      struct iattr *attr, char *data) +int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data)  { +	struct gfs2_ea_location el;  	struct buffer_head *dibh;  	int error; -	if (GFS2_EA_IS_STUFFED(el->el_ea)) { +	error = gfs2_ea_find(ip, GFS2_EATYPE_SYS, GFS2_POSIX_ACL_ACCESS, &el); +	if (error) +		return error; + +	if (GFS2_EA_IS_STUFFED(el.el_ea)) {  		error = gfs2_trans_begin(GFS2_SB(&ip->i_inode), RES_DINODE + RES_EATTR, 0);  		if (error)  			return error; -		gfs2_trans_add_bh(ip->i_gl, el->el_bh, 1); -		memcpy(GFS2_EA2DATA(el->el_ea), data, -		       GFS2_EA_DATA_LEN(el->el_ea)); +		gfs2_trans_add_bh(ip->i_gl, el.el_bh, 1); +		memcpy(GFS2_EA2DATA(el.el_ea), data, +		       GFS2_EA_DATA_LEN(el.el_ea));  	} else -		error = ea_acl_chmod_unstuffed(ip, el->el_ea, data); +		error = ea_acl_chmod_unstuffed(ip, el.el_ea, data);  	if (error)  		return error; @@ -1507,18 +1541,6 @@ static int gfs2_xattr_user_set(struct inode *inode, const char *name,  	return gfs2_xattr_set(inode, GFS2_EATYPE_USR, name, value, size, flags);  } -static int gfs2_xattr_system_get(struct inode *inode, const char *name, -				 void *buffer, size_t size) -{ -	return gfs2_xattr_get(inode, GFS2_EATYPE_SYS, name, buffer, size); -} - -static int gfs2_xattr_system_set(struct inode *inode, const char *name, -				 const void *value, size_t size, int flags) -{ -	return gfs2_xattr_set(inode, GFS2_EATYPE_SYS, name, value, size, flags); -} -  static int gfs2_xattr_security_get(struct inode *inode, const char *name,  				   void *buffer, size_t size)  { @@ -1543,12 +1565,6 @@ static struct xattr_handler gfs2_xattr_security_handler = {  	.set    = gfs2_xattr_security_set,  }; -static struct xattr_handler gfs2_xattr_system_handler = { -	.prefix = XATTR_SYSTEM_PREFIX, -	.get    = gfs2_xattr_system_get, -	.set    = gfs2_xattr_system_set, -}; -  struct xattr_handler *gfs2_xattr_handlers[] = {  	&gfs2_xattr_user_handler,  	&gfs2_xattr_security_handler, diff --git a/fs/gfs2/xattr.h b/fs/gfs2/xattr.h index cbdfd774373..8d6ae5813c4 100644 --- a/fs/gfs2/xattr.h +++ b/fs/gfs2/xattr.h @@ -62,11 +62,7 @@ extern int gfs2_ea_dealloc(struct gfs2_inode *ip);  /* Exported to acl.c */ -extern int gfs2_ea_find(struct gfs2_inode *ip, int type, const char *name, -			struct gfs2_ea_location *el); -extern int gfs2_ea_get_copy(struct gfs2_inode *ip, struct gfs2_ea_location *el, -			    char *data, size_t size); -extern int gfs2_ea_acl_chmod(struct gfs2_inode *ip, struct gfs2_ea_location *el, -			     struct iattr *attr, char *data); +extern int gfs2_xattr_acl_get(struct gfs2_inode *ip, const char *name, char **data); +extern int gfs2_xattr_acl_chmod(struct gfs2_inode *ip, struct iattr *attr, char *data);  #endif /* __EATTR_DOT_H__ */ diff --git a/fs/inode.c b/fs/inode.c index 4d8e3be5597..06c1f02de61 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -18,7 +18,6 @@  #include <linux/hash.h>  #include <linux/swap.h>  #include <linux/security.h> -#include <linux/ima.h>  #include <linux/pagemap.h>  #include <linux/cdev.h>  #include <linux/bootmem.h> @@ -157,11 +156,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)  	if (security_inode_alloc(inode))  		goto out; - -	/* allocate and initialize an i_integrity */ -	if (ima_inode_alloc(inode)) -		goto out_free_security; -  	spin_lock_init(&inode->i_lock);  	lockdep_set_class(&inode->i_lock, &sb->s_type->i_lock_key); @@ -201,9 +195,6 @@ int inode_init_always(struct super_block *sb, struct inode *inode)  #endif  	return 0; - -out_free_security: -	security_inode_free(inode);  out:  	return -ENOMEM;  } @@ -235,7 +226,6 @@ static struct inode *alloc_inode(struct super_block *sb)  void __destroy_inode(struct inode *inode)  {  	BUG_ON(inode_has_buffers(inode)); -	ima_inode_free(inode);  	security_inode_free(inode);  	fsnotify_inode_delete(inode);  #ifdef CONFIG_FS_POSIX_ACL diff --git a/fs/namespace.c b/fs/namespace.c index bdc3cb4fd22..7d70d63ceb2 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1921,6 +1921,16 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,  	if (data_page)  		((char *)data_page)[PAGE_SIZE - 1] = 0; +	/* ... and get the mountpoint */ +	retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); +	if (retval) +		return retval; + +	retval = security_sb_mount(dev_name, &path, +				   type_page, flags, data_page); +	if (retval) +		goto dput_out; +  	/* Default to relatime unless overriden */  	if (!(flags & MS_NOATIME))  		mnt_flags |= MNT_RELATIME; @@ -1945,16 +1955,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page,  		   MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |  		   MS_STRICTATIME); -	/* ... and get the mountpoint */ -	retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); -	if (retval) -		return retval; - -	retval = security_sb_mount(dev_name, &path, -				   type_page, flags, data_page); -	if (retval) -		goto dput_out; -  	if (flags & MS_REMOUNT)  		retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,  				    data_page); diff --git a/fs/open.c b/fs/open.c index 4f01e06227c..b4b31d277f3 100644 --- a/fs/open.c +++ b/fs/open.c @@ -587,6 +587,9 @@ SYSCALL_DEFINE1(chroot, const char __user *, filename)  	error = -EPERM;  	if (!capable(CAP_SYS_CHROOT))  		goto dput_and_out; +	error = security_path_chroot(&path); +	if (error) +		goto dput_and_out;  	set_fs_root(current->fs, &path);  	error = 0; @@ -617,11 +620,15 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, mode_t, mode)  	if (err)  		goto out_putf;  	mutex_lock(&inode->i_mutex); +	err = security_path_chmod(dentry, file->f_vfsmnt, mode); +	if (err) +		goto out_unlock;  	if (mode == (mode_t) -1)  		mode = inode->i_mode;  	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);  	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;  	err = notify_change(dentry, &newattrs); +out_unlock:  	mutex_unlock(&inode->i_mutex);  	mnt_drop_write(file->f_path.mnt);  out_putf: @@ -646,11 +653,15 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode)  	if (error)  		goto dput_and_out;  	mutex_lock(&inode->i_mutex); +	error = security_path_chmod(path.dentry, path.mnt, mode); +	if (error) +		goto out_unlock;  	if (mode == (mode_t) -1)  		mode = inode->i_mode;  	newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);  	newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;  	error = notify_change(path.dentry, &newattrs); +out_unlock:  	mutex_unlock(&inode->i_mutex);  	mnt_drop_write(path.mnt);  dput_and_out: @@ -664,9 +675,9 @@ SYSCALL_DEFINE2(chmod, const char __user *, filename, mode_t, mode)  	return sys_fchmodat(AT_FDCWD, filename, mode);  } -static int chown_common(struct dentry * dentry, uid_t user, gid_t group) +static int chown_common(struct path *path, uid_t user, gid_t group)  { -	struct inode *inode = dentry->d_inode; +	struct inode *inode = path->dentry->d_inode;  	int error;  	struct iattr newattrs; @@ -683,7 +694,9 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)  		newattrs.ia_valid |=  			ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;  	mutex_lock(&inode->i_mutex); -	error = notify_change(dentry, &newattrs); +	error = security_path_chown(path, user, group); +	if (!error) +		error = notify_change(path->dentry, &newattrs);  	mutex_unlock(&inode->i_mutex);  	return error; @@ -700,7 +713,7 @@ SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)  	error = mnt_want_write(path.mnt);  	if (error)  		goto out_release; -	error = chown_common(path.dentry, user, group); +	error = chown_common(&path, user, group);  	mnt_drop_write(path.mnt);  out_release:  	path_put(&path); @@ -725,7 +738,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,  	error = mnt_want_write(path.mnt);  	if (error)  		goto out_release; -	error = chown_common(path.dentry, user, group); +	error = chown_common(&path, user, group);  	mnt_drop_write(path.mnt);  out_release:  	path_put(&path); @@ -744,7 +757,7 @@ SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group  	error = mnt_want_write(path.mnt);  	if (error)  		goto out_release; -	error = chown_common(path.dentry, user, group); +	error = chown_common(&path, user, group);  	mnt_drop_write(path.mnt);  out_release:  	path_put(&path); @@ -767,7 +780,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)  		goto out_fput;  	dentry = file->f_path.dentry;  	audit_inode(NULL, dentry); -	error = chown_common(dentry, user, group); +	error = chown_common(&file->f_path, user, group);  	mnt_drop_write(file->f_path.mnt);  out_fput:  	fput(file); diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig index 8047e01ef46..353e78a9ebe 100644 --- a/fs/quota/Kconfig +++ b/fs/quota/Kconfig @@ -17,7 +17,7 @@ config QUOTA  config QUOTA_NETLINK_INTERFACE  	bool "Report quota messages through netlink interface" -	depends on QUOTA && NET +	depends on QUOTACTL && NET  	help  	  If you say Y here, quota warnings (about exceeding softlimit, reaching  	  hardlimit, etc.) will be reported through netlink interface. If unsure, diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 39b49c42a7e..9b6ad908dcb 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -77,10 +77,6 @@  #include <linux/capability.h>  #include <linux/quotaops.h>  #include <linux/writeback.h> /* for inode_lock, oddly enough.. */ -#ifdef CONFIG_QUOTA_NETLINK_INTERFACE -#include <net/netlink.h> -#include <net/genetlink.h> -#endif  #include <asm/uaccess.h> @@ -1071,73 +1067,6 @@ static void print_warning(struct dquot *dquot, const int warntype)  }  #endif -#ifdef CONFIG_QUOTA_NETLINK_INTERFACE - -/* Netlink family structure for quota */ -static struct genl_family quota_genl_family = { -	.id = GENL_ID_GENERATE, -	.hdrsize = 0, -	.name = "VFS_DQUOT", -	.version = 1, -	.maxattr = QUOTA_NL_A_MAX, -}; - -/* Send warning to userspace about user which exceeded quota */ -static void send_warning(const struct dquot *dquot, const char warntype) -{ -	static atomic_t seq; -	struct sk_buff *skb; -	void *msg_head; -	int ret; -	int msg_size = 4 * nla_total_size(sizeof(u32)) + -		       2 * nla_total_size(sizeof(u64)); - -	/* We have to allocate using GFP_NOFS as we are called from a -	 * filesystem performing write and thus further recursion into -	 * the fs to free some data could cause deadlocks. */ -	skb = genlmsg_new(msg_size, GFP_NOFS); -	if (!skb) { -		printk(KERN_ERR -		  "VFS: Not enough memory to send quota warning.\n"); -		return; -	} -	msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq), -			"a_genl_family, 0, QUOTA_NL_C_WARNING); -	if (!msg_head) { -		printk(KERN_ERR -		  "VFS: Cannot store netlink header in quota warning.\n"); -		goto err_out; -	} -	ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, dquot->dq_type); -	if (ret) -		goto attr_err_out; -	ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, dquot->dq_id); -	if (ret) -		goto attr_err_out; -	ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); -	if (ret) -		goto attr_err_out; -	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, -		MAJOR(dquot->dq_sb->s_dev)); -	if (ret) -		goto attr_err_out; -	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, -		MINOR(dquot->dq_sb->s_dev)); -	if (ret) -		goto attr_err_out; -	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid()); -	if (ret) -		goto attr_err_out; -	genlmsg_end(skb, msg_head); - -	genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); -	return; -attr_err_out: -	printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); -err_out: -	kfree_skb(skb); -} -#endif  /*   * Write warnings to the console and send warning messages over netlink.   * @@ -1145,18 +1074,20 @@ err_out:   */  static void flush_warnings(struct dquot *const *dquots, char *warntype)  { +	struct dquot *dq;  	int i; -	for (i = 0; i < MAXQUOTAS; i++) -		if (dquots[i] && warntype[i] != QUOTA_NL_NOWARN && -		    !warning_issued(dquots[i], warntype[i])) { +	for (i = 0; i < MAXQUOTAS; i++) { +		dq = dquots[i]; +		if (dq && warntype[i] != QUOTA_NL_NOWARN && +		    !warning_issued(dq, warntype[i])) {  #ifdef CONFIG_PRINT_QUOTA_WARNING -			print_warning(dquots[i], warntype[i]); -#endif -#ifdef CONFIG_QUOTA_NETLINK_INTERFACE -			send_warning(dquots[i], warntype[i]); +			print_warning(dq, warntype[i]);  #endif +			quota_send_warning(dq->dq_type, dq->dq_id, +					   dq->dq_sb->s_dev, warntype[i]);  		} +	}  }  static int ignore_hardlimit(struct dquot *dquot) @@ -2607,12 +2538,6 @@ static int __init dquot_init(void)  	register_shrinker(&dqcache_shrinker); -#ifdef CONFIG_QUOTA_NETLINK_INTERFACE -	if (genl_register_family("a_genl_family) != 0) -		printk(KERN_ERR -		       "VFS: Failed to create quota netlink interface.\n"); -#endif -  	return 0;  }  module_init(dquot_init); diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 95c5b42384b..ee91e275695 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -18,6 +18,8 @@  #include <linux/capability.h>  #include <linux/quotaops.h>  #include <linux/types.h> +#include <net/netlink.h> +#include <net/genetlink.h>  /* Check validity of generic quotactl commands */  static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, @@ -525,3 +527,94 @@ asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,  	return ret;  }  #endif + + +#ifdef CONFIG_QUOTA_NETLINK_INTERFACE + +/* Netlink family structure for quota */ +static struct genl_family quota_genl_family = { +	.id = GENL_ID_GENERATE, +	.hdrsize = 0, +	.name = "VFS_DQUOT", +	.version = 1, +	.maxattr = QUOTA_NL_A_MAX, +}; + +/** + * quota_send_warning - Send warning to userspace about exceeded quota + * @type: The quota type: USRQQUOTA, GRPQUOTA,... + * @id: The user or group id of the quota that was exceeded + * @dev: The device on which the fs is mounted (sb->s_dev) + * @warntype: The type of the warning: QUOTA_NL_... + * + * This can be used by filesystems (including those which don't use + * dquot) to send a message to userspace relating to quota limits. + * + */ + +void quota_send_warning(short type, unsigned int id, dev_t dev, +			const char warntype) +{ +	static atomic_t seq; +	struct sk_buff *skb; +	void *msg_head; +	int ret; +	int msg_size = 4 * nla_total_size(sizeof(u32)) + +		       2 * nla_total_size(sizeof(u64)); + +	/* We have to allocate using GFP_NOFS as we are called from a +	 * filesystem performing write and thus further recursion into +	 * the fs to free some data could cause deadlocks. */ +	skb = genlmsg_new(msg_size, GFP_NOFS); +	if (!skb) { +		printk(KERN_ERR +		  "VFS: Not enough memory to send quota warning.\n"); +		return; +	} +	msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq), +			"a_genl_family, 0, QUOTA_NL_C_WARNING); +	if (!msg_head) { +		printk(KERN_ERR +		  "VFS: Cannot store netlink header in quota warning.\n"); +		goto err_out; +	} +	ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type); +	if (ret) +		goto attr_err_out; +	ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id); +	if (ret) +		goto attr_err_out; +	ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); +	if (ret) +		goto attr_err_out; +	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev)); +	if (ret) +		goto attr_err_out; +	ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); +	if (ret) +		goto attr_err_out; +	ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid()); +	if (ret) +		goto attr_err_out; +	genlmsg_end(skb, msg_head); + +	genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); +	return; +attr_err_out: +	printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); +err_out: +	kfree_skb(skb); +} +EXPORT_SYMBOL(quota_send_warning); + +static int __init quota_init(void) +{ +	if (genl_register_family("a_genl_family) != 0) +		printk(KERN_ERR +		       "VFS: Failed to create quota netlink interface.\n"); +	return 0; +}; + +module_init(quota_init); +#endif + diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c index c6ad7c7e3ee..05ac0fe9c4d 100644 --- a/fs/xattr_acl.c +++ b/fs/xattr_acl.c @@ -36,7 +36,7 @@ posix_acl_from_xattr(const void *value, size_t size)  	if (count == 0)  		return NULL; -	acl = posix_acl_alloc(count, GFP_KERNEL); +	acl = posix_acl_alloc(count, GFP_NOFS);  	if (!acl)  		return ERR_PTR(-ENOMEM);  	acl_e = acl->a_entries; diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 1feed71551c..5a5385749e1 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -330,6 +330,7 @@ unifdef-y += scc.h  unifdef-y += sched.h  unifdef-y += screen_info.h  unifdef-y += sdla.h +unifdef-y += securebits.h  unifdef-y += selinux_netlink.h  unifdef-y += sem.h  unifdef-y += serial_core.h diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h index dd97fb8408a..b10ec49ee2d 100644 --- a/include/linux/bootmem.h +++ b/include/linux/bootmem.h @@ -53,6 +53,7 @@ extern void free_bootmem_node(pg_data_t *pgdat,  			      unsigned long addr,  			      unsigned long size);  extern void free_bootmem(unsigned long addr, unsigned long size); +extern void free_bootmem_late(unsigned long addr, unsigned long size);  /*   * Flags for reserve_bootmem (also if CONFIG_HAVE_ARCH_BOOTMEM_NODE, diff --git a/include/linux/capability.h b/include/linux/capability.h index c8f2a5f70ed..39e5ff512fb 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -92,9 +92,7 @@ struct vfs_cap_data {  #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3  #define _KERNEL_CAPABILITY_U32S    _LINUX_CAPABILITY_U32S_3 -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  extern int file_caps_enabled; -#endif  typedef struct kernel_cap_struct {  	__u32 cap[_KERNEL_CAPABILITY_U32S]; diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index a3ed7cb8ca3..73dcf804bc9 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -79,6 +79,7 @@  #define  noinline			__attribute__((noinline))  #define __attribute_const__		__attribute__((__const__))  #define __maybe_unused			__attribute__((unused)) +#define __always_unused			__attribute__((unused))  #define __gcc_header(x) #x  #define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h) diff --git a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h index 450fa597c94..ab3af40a53c 100644 --- a/include/linux/compiler-gcc4.h +++ b/include/linux/compiler-gcc4.h @@ -36,4 +36,18 @@     the kernel context */  #define __cold			__attribute__((__cold__)) + +#if __GNUC_MINOR__ >= 5 +/* + * Mark a position in code as unreachable.  This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased.  Really, we need to have autoconf for the kernel. + */ +#define unreachable() __builtin_unreachable() +#endif +  #endif diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 04fb5135b4e..acbd654cc85 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -144,6 +144,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);  # define barrier() __memory_barrier()  #endif +/* Unreachable code */ +#ifndef unreachable +# define unreachable() do { } while (1) +#endif +  #ifndef RELOC_HIDE  # define RELOC_HIDE(ptr, off)					\    ({ unsigned long __ptr;					\ @@ -213,6 +218,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);  # define __maybe_unused		/* unimplemented */  #endif +#ifndef __always_unused +# define __always_unused	/* unimplemented */ +#endif +  #ifndef noinline  #define noinline  #endif diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 4a2b162c256..5de4c9e5856 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -208,16 +208,9 @@ struct dmar_atsr_unit {  	u8 include_all:1;		/* include all ports */  }; -/* Intel DMAR  initialization functions */  extern int intel_iommu_init(void); -#else -static inline int intel_iommu_init(void) -{ -#ifdef CONFIG_INTR_REMAP -	return dmar_dev_scope_init(); -#else -	return -ENODEV; -#endif -} -#endif /* !CONFIG_DMAR */ +#else /* !CONFIG_DMAR: */ +static inline int intel_iommu_init(void) { return -ENODEV; } +#endif /* CONFIG_DMAR */ +  #endif /* __DMAR_H__ */ diff --git a/include/linux/gfs2_ondisk.h b/include/linux/gfs2_ondisk.h index b80c88dedbb..81f90a59cda 100644 --- a/include/linux/gfs2_ondisk.h +++ b/include/linux/gfs2_ondisk.h @@ -81,7 +81,11 @@ struct gfs2_meta_header {  	__be32 mh_type;  	__be64 __pad0;		/* Was generation number in gfs1 */  	__be32 mh_format; -	__be32 __pad1;		/* Was incarnation number in gfs1 */ +	/* This union is to keep userspace happy */ +	union { +		__be32 mh_jid;		/* Was incarnation number in gfs1 */ +		__be32 __pad1; +	};  };  /* diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h index 6d527ee82b2..d5b387669da 100644 --- a/include/linux/hardirq.h +++ b/include/linux/hardirq.h @@ -139,10 +139,34 @@ static inline void account_system_vtime(struct task_struct *tsk)  #endif  #if defined(CONFIG_NO_HZ) +#if defined(CONFIG_TINY_RCU) +extern void rcu_enter_nohz(void); +extern void rcu_exit_nohz(void); + +static inline void rcu_irq_enter(void) +{ +	rcu_exit_nohz(); +} + +static inline void rcu_irq_exit(void) +{ +	rcu_enter_nohz(); +} + +static inline void rcu_nmi_enter(void) +{ +} + +static inline void rcu_nmi_exit(void) +{ +} + +#else  extern void rcu_irq_enter(void);  extern void rcu_irq_exit(void);  extern void rcu_nmi_enter(void);  extern void rcu_nmi_exit(void); +#endif  #else  # define rcu_irq_enter() do { } while (0)  # define rcu_irq_exit() do { } while (0) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 21a6f5d9af2..8d10aa7fd4c 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -83,16 +83,12 @@ extern struct group_info init_groups;  #define INIT_IDS  #endif -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  /*   * Because of the reduced scope of CAP_SETPCAP when filesystem   * capabilities are in effect, it is safe to allow CAP_SETPCAP to   * be available in the default configuration.   */  # define CAP_INIT_BSET  CAP_FULL_SET -#else -# define CAP_INIT_BSET  CAP_INIT_EFF_SET -#endif  #ifdef CONFIG_TREE_PREEMPT_RCU  #define INIT_TASK_RCU_PREEMPT(tsk)					\ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 7ca72b74eec..75f3f00ac1e 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -603,12 +603,6 @@ static inline void init_irq_proc(void)  }  #endif -#if defined(CONFIG_GENERIC_HARDIRQS) && defined(CONFIG_DEBUG_SHIRQ) -extern void debug_poll_all_shared_irqs(void); -#else -static inline void debug_poll_all_shared_irqs(void) { } -#endif -  struct seq_file;  int show_interrupts(struct seq_file *p, void *v); diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index b02a3f1d46a..006bf45eae3 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -124,6 +124,6 @@  	typecheck(unsigned long, flags);	\  	raw_irqs_disabled_flags(flags);		\  }) -#endif		/* CONFIG_X86 */ +#endif /* CONFIG_TRACE_IRQFLAGS_SUPPORT */  #endif diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f4e3184fa05..3fa4c590cf1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -15,7 +15,6 @@  #include <linux/bitops.h>  #include <linux/log2.h>  #include <linux/typecheck.h> -#include <linux/ratelimit.h>  #include <linux/dynamic_debug.h>  #include <asm/byteorder.h>  #include <asm/bug.h> @@ -241,8 +240,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)  asmlinkage int printk(const char * fmt, ...)  	__attribute__ ((format (printf, 1, 2))) __cold; -extern struct ratelimit_state printk_ratelimit_state; -extern int printk_ratelimit(void); +extern int __printk_ratelimit(const char *func); +#define printk_ratelimit() __printk_ratelimit(__func__)  extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,  				   unsigned int interval_msec); diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index 190c3785487..f78f83d7663 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h @@ -26,14 +26,15 @@  /* Auxiliary data to use in generating the audit record. */  struct common_audit_data { -	char    type; -#define LSM_AUDIT_DATA_FS      1 -#define LSM_AUDIT_DATA_NET     2 -#define LSM_AUDIT_DATA_CAP     3 -#define LSM_AUDIT_DATA_IPC     4 -#define LSM_AUDIT_DATA_TASK    5 -#define LSM_AUDIT_DATA_KEY     6 -#define LSM_AUDIT_NO_AUDIT     7 +	char type; +#define LSM_AUDIT_DATA_FS	1 +#define LSM_AUDIT_DATA_NET	2 +#define LSM_AUDIT_DATA_CAP	3 +#define LSM_AUDIT_DATA_IPC	4 +#define LSM_AUDIT_DATA_TASK	5 +#define LSM_AUDIT_DATA_KEY	6 +#define LSM_AUDIT_NO_AUDIT	7 +#define LSM_AUDIT_DATA_KMOD	8  	struct task_struct *tsk;  	union 	{  		struct { @@ -66,6 +67,7 @@ struct common_audit_data {  			char *key_desc;  		} key_struct;  #endif +		char *kmod_name;  	} u;  	/* this union contains LSM specific data */  	union { diff --git a/include/linux/mfd/wm831x/regulator.h b/include/linux/mfd/wm831x/regulator.h index f95466343fb..955d30fc6a2 100644 --- a/include/linux/mfd/wm831x/regulator.h +++ b/include/linux/mfd/wm831x/regulator.h @@ -1212,7 +1212,7 @@  #define WM831X_LDO1_OK_SHIFT                         0  /* LDO1_OK */  #define WM831X_LDO1_OK_WIDTH                         1  /* LDO1_OK */ -#define WM831X_ISINK_MAX_ISEL 56 -extern int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL]; +#define WM831X_ISINK_MAX_ISEL 55 +extern int wm831x_isinkv_values[WM831X_ISINK_MAX_ISEL + 1];  #endif diff --git a/include/linux/net.h b/include/linux/net.h index 6ce87663551..5e8083cacc8 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -280,6 +280,7 @@ extern int kernel_sock_shutdown(struct socket *sock,  #ifdef CONFIG_SYSCTL  #include <linux/sysctl.h> +#include <linux/ratelimit.h>  extern struct ratelimit_state net_ratelimit_state;  #endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 84cf1f3b783..daecca3c830 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1633,6 +1633,8 @@  #define PCI_DEVICE_ID_O2_6730		0x673a  #define PCI_DEVICE_ID_O2_6832		0x6832  #define PCI_DEVICE_ID_O2_6836		0x6836 +#define PCI_DEVICE_ID_O2_6812		0x6872 +#define PCI_DEVICE_ID_O2_6933		0x6933  #define PCI_VENDOR_ID_3DFX		0x121a  #define PCI_DEVICE_ID_3DFX_VOODOO	0x0001 diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 065a3652a3e..67608161df6 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -147,6 +147,20 @@ static inline void forget_cached_acl(struct inode *inode, int type)  	if (old != ACL_NOT_CACHED)  		posix_acl_release(old);  } + +static inline void forget_all_cached_acls(struct inode *inode) +{ +	struct posix_acl *old_access, *old_default; +	spin_lock(&inode->i_lock); +	old_access = inode->i_acl; +	old_default = inode->i_default_acl; +	inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; +	spin_unlock(&inode->i_lock); +	if (old_access != ACL_NOT_CACHED) +		posix_acl_release(old_access); +	if (old_default != ACL_NOT_CACHED) +		posix_acl_release(old_default); +}  #endif  static inline void cache_no_acl(struct inode *inode) diff --git a/include/linux/quota.h b/include/linux/quota.h index 78c48895b12..ce9a9b2e5cd 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -376,6 +376,17 @@ static inline unsigned int dquot_generic_flag(unsigned int flags, int type)  	return flags >> _DQUOT_STATE_FLAGS;  } +#ifdef CONFIG_QUOTA_NETLINK_INTERFACE +extern void quota_send_warning(short type, unsigned int id, dev_t dev, +			       const char warntype); +#else +static inline void quota_send_warning(short type, unsigned int id, dev_t dev, +				      const char warntype) +{ +	return; +} +#endif /* CONFIG_QUOTA_NETLINK_INTERFACE */ +  struct quota_info {  	unsigned int flags;			/* Flags for diskquotas on this device */  	struct mutex dqio_mutex;		/* lock device while I/O in progress */ diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h index 00044b85645..668cf1bef03 100644 --- a/include/linux/ratelimit.h +++ b/include/linux/ratelimit.h @@ -1,20 +1,31 @@  #ifndef _LINUX_RATELIMIT_H  #define _LINUX_RATELIMIT_H +  #include <linux/param.h> +#include <linux/spinlock_types.h> -#define DEFAULT_RATELIMIT_INTERVAL (5 * HZ) -#define DEFAULT_RATELIMIT_BURST 10 +#define DEFAULT_RATELIMIT_INTERVAL	(5 * HZ) +#define DEFAULT_RATELIMIT_BURST		10  struct ratelimit_state { -	int interval; -	int burst; -	int printed; -	int missed; -	unsigned long begin; +	spinlock_t	lock;		/* protect the state */ + +	int		interval; +	int		burst; +	int		printed; +	int		missed; +	unsigned long	begin;  }; -#define DEFINE_RATELIMIT_STATE(name, interval, burst)		\ -		struct ratelimit_state name = {interval, burst,} +#define DEFINE_RATELIMIT_STATE(name, interval_init, burst_init)		\ +									\ +	struct ratelimit_state name = {					\ +		.lock		= __SPIN_LOCK_UNLOCKED(name.lock),	\ +		.interval	= interval_init,			\ +		.burst		= burst_init,				\ +	} + +extern int ___ratelimit(struct ratelimit_state *rs, const char *func); +#define __ratelimit(state) ___ratelimit(state, __func__) -extern int __ratelimit(struct ratelimit_state *rs); -#endif +#endif /* _LINUX_RATELIMIT_H */ diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 3ebd0b7bcb0..24440f4bf47 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -52,11 +52,6 @@ struct rcu_head {  };  /* Exported common interfaces */ -#ifdef CONFIG_TREE_PREEMPT_RCU -extern void synchronize_rcu(void); -#else /* #ifdef CONFIG_TREE_PREEMPT_RCU */ -#define synchronize_rcu synchronize_sched -#endif /* #else #ifdef CONFIG_TREE_PREEMPT_RCU */  extern void synchronize_rcu_bh(void);  extern void synchronize_sched(void);  extern void rcu_barrier(void); @@ -67,12 +62,11 @@ extern int sched_expedited_torture_stats(char *page);  /* Internal to kernel */  extern void rcu_init(void); -extern void rcu_scheduler_starting(void); -extern int rcu_needs_cpu(int cpu); -extern int rcu_scheduler_active;  #if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)  #include <linux/rcutree.h> +#elif defined(CONFIG_TINY_RCU) +#include <linux/rcutiny.h>  #else  #error "Unknown RCU implementation specified to kernel configuration"  #endif diff --git a/include/linux/rcutiny.h b/include/linux/rcutiny.h new file mode 100644 index 00000000000..c4ba9a78721 --- /dev/null +++ b/include/linux/rcutiny.h @@ -0,0 +1,104 @@ +/* + * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2008 + * + * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + * + * For detailed explanation of Read-Copy Update mechanism see - + *		Documentation/RCU + */ +#ifndef __LINUX_TINY_H +#define __LINUX_TINY_H + +#include <linux/cache.h> + +void rcu_sched_qs(int cpu); +void rcu_bh_qs(int cpu); + +#define __rcu_read_lock()	preempt_disable() +#define __rcu_read_unlock()	preempt_enable() +#define __rcu_read_lock_bh()	local_bh_disable() +#define __rcu_read_unlock_bh()	local_bh_enable() +#define call_rcu_sched		call_rcu + +#define rcu_init_sched()	do { } while (0) +extern void rcu_check_callbacks(int cpu, int user); + +static inline int rcu_needs_cpu(int cpu) +{ +	return 0; +} + +/* + * Return the number of grace periods. + */ +static inline long rcu_batches_completed(void) +{ +	return 0; +} + +/* + * Return the number of bottom-half grace periods. + */ +static inline long rcu_batches_completed_bh(void) +{ +	return 0; +} + +extern int rcu_expedited_torture_stats(char *page); + +#define synchronize_rcu synchronize_sched + +static inline void synchronize_rcu_expedited(void) +{ +	synchronize_sched(); +} + +static inline void synchronize_rcu_bh_expedited(void) +{ +	synchronize_sched(); +} + +struct notifier_block; + +#ifdef CONFIG_NO_HZ + +extern void rcu_enter_nohz(void); +extern void rcu_exit_nohz(void); + +#else /* #ifdef CONFIG_NO_HZ */ + +static inline void rcu_enter_nohz(void) +{ +} + +static inline void rcu_exit_nohz(void) +{ +} + +#endif /* #else #ifdef CONFIG_NO_HZ */ + +static inline void rcu_scheduler_starting(void) +{ +} + +static inline void exit_rcu(void) +{ +} + +#endif /* __LINUX_RCUTINY_H */ diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h index 9642c6bcb39..c93eee5911b 100644 --- a/include/linux/rcutree.h +++ b/include/linux/rcutree.h @@ -34,15 +34,15 @@ struct notifier_block;  extern void rcu_sched_qs(int cpu);  extern void rcu_bh_qs(int cpu); -extern int rcu_cpu_notify(struct notifier_block *self, -			  unsigned long action, void *hcpu);  extern int rcu_needs_cpu(int cpu); +extern void rcu_scheduler_starting(void);  extern int rcu_expedited_torture_stats(char *page);  #ifdef CONFIG_TREE_PREEMPT_RCU  extern void __rcu_read_lock(void);  extern void __rcu_read_unlock(void); +extern void synchronize_rcu(void);  extern void exit_rcu(void);  #else /* #ifdef CONFIG_TREE_PREEMPT_RCU */ @@ -57,7 +57,7 @@ static inline void __rcu_read_unlock(void)  	preempt_enable();  } -#define __synchronize_sched() synchronize_rcu() +#define synchronize_rcu synchronize_sched  static inline void exit_rcu(void)  { @@ -83,7 +83,6 @@ static inline void synchronize_rcu_bh_expedited(void)  	synchronize_sched_expedited();  } -extern void __rcu_init(void);  extern void rcu_check_callbacks(int cpu, int user);  extern long rcu_batches_completed(void); diff --git a/include/linux/sched.h b/include/linux/sched.h index 75e6e60bf58..882dc48163b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1421,17 +1421,17 @@ struct task_struct {  #endif  #ifdef CONFIG_TRACE_IRQFLAGS  	unsigned int irq_events; -	int hardirqs_enabled;  	unsigned long hardirq_enable_ip; -	unsigned int hardirq_enable_event;  	unsigned long hardirq_disable_ip; +	unsigned int hardirq_enable_event;  	unsigned int hardirq_disable_event; -	int softirqs_enabled; +	int hardirqs_enabled; +	int hardirq_context;  	unsigned long softirq_disable_ip; -	unsigned int softirq_disable_event;  	unsigned long softirq_enable_ip; +	unsigned int softirq_disable_event;  	unsigned int softirq_enable_event; -	int hardirq_context; +	int softirqs_enabled;  	int softirq_context;  #endif  #ifdef CONFIG_LOCKDEP @@ -2086,11 +2086,18 @@ static inline int is_si_special(const struct siginfo *info)  	return info <= SEND_SIG_FORCED;  } -/* True if we are on the alternate signal stack.  */ - +/* + * True if we are on the alternate signal stack. + */  static inline int on_sig_stack(unsigned long sp)  { -	return (sp - current->sas_ss_sp < current->sas_ss_size); +#ifdef CONFIG_STACK_GROWSUP +	return sp >= current->sas_ss_sp && +		sp - current->sas_ss_sp < current->sas_ss_size; +#else +	return sp > current->sas_ss_sp && +		sp - current->sas_ss_sp <= current->sas_ss_size; +#endif  }  static inline int sas_ss_flags(unsigned long sp) diff --git a/include/linux/securebits.h b/include/linux/securebits.h index d2c5ed845bc..33406174cbe 100644 --- a/include/linux/securebits.h +++ b/include/linux/securebits.h @@ -1,6 +1,15 @@  #ifndef _LINUX_SECUREBITS_H  #define _LINUX_SECUREBITS_H 1 +/* Each securesetting is implemented using two bits. One bit specifies +   whether the setting is on or off. The other bit specify whether the +   setting is locked or not. A setting which is locked cannot be +   changed from user-level. */ +#define issecure_mask(X)	(1 << (X)) +#ifdef __KERNEL__ +#define issecure(X)		(issecure_mask(X) & current_cred_xxx(securebits)) +#endif +  #define SECUREBITS_DEFAULT 0x00000000  /* When set UID 0 has no special privileges. When unset, we support @@ -12,6 +21,9 @@  #define SECURE_NOROOT			0  #define SECURE_NOROOT_LOCKED		1  /* make bit-0 immutable */ +#define SECBIT_NOROOT		(issecure_mask(SECURE_NOROOT)) +#define SECBIT_NOROOT_LOCKED	(issecure_mask(SECURE_NOROOT_LOCKED)) +  /* When set, setuid to/from uid 0 does not trigger capability-"fixup".     When unset, to provide compatiblility with old programs relying on     set*uid to gain/lose privilege, transitions to/from uid 0 cause @@ -19,6 +31,10 @@  #define SECURE_NO_SETUID_FIXUP		2  #define SECURE_NO_SETUID_FIXUP_LOCKED	3  /* make bit-2 immutable */ +#define SECBIT_NO_SETUID_FIXUP	(issecure_mask(SECURE_NO_SETUID_FIXUP)) +#define SECBIT_NO_SETUID_FIXUP_LOCKED \ +			(issecure_mask(SECURE_NO_SETUID_FIXUP_LOCKED)) +  /* When set, a process can retain its capabilities even after     transitioning to a non-root user (the set-uid fixup suppressed by     bit 2). Bit-4 is cleared when a process calls exec(); setting both @@ -27,12 +43,8 @@  #define SECURE_KEEP_CAPS		4  #define SECURE_KEEP_CAPS_LOCKED		5  /* make bit-4 immutable */ -/* Each securesetting is implemented using two bits. One bit specifies -   whether the setting is on or off. The other bit specify whether the -   setting is locked or not. A setting which is locked cannot be -   changed from user-level. */ -#define issecure_mask(X)	(1 << (X)) -#define issecure(X)		(issecure_mask(X) & current_cred_xxx(securebits)) +#define SECBIT_KEEP_CAPS	(issecure_mask(SECURE_KEEP_CAPS)) +#define SECBIT_KEEP_CAPS_LOCKED (issecure_mask(SECURE_KEEP_CAPS_LOCKED))  #define SECURE_ALL_BITS		(issecure_mask(SECURE_NOROOT) | \  				 issecure_mask(SECURE_NO_SETUID_FIXUP) | \ diff --git a/include/linux/security.h b/include/linux/security.h index 239e40d0450..466cbadbd1e 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -447,6 +447,22 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)   *	@new_dir contains the path structure for parent of the new link.   *	@new_dentry contains the dentry structure of the new link.   *	Return 0 if permission is granted. + * @path_chmod: + *	Check for permission to change DAC's permission of a file or directory. + *	@dentry contains the dentry structure. + *	@mnt contains the vfsmnt structure. + *	@mode contains DAC's mode. + *	Return 0 if permission is granted. + * @path_chown: + *	Check for permission to change owner/group of a file or directory. + *	@path contains the path structure. + *	@uid contains new owner's ID. + *	@gid contains new group's ID. + *	Return 0 if permission is granted. + * @path_chroot: + *	Check for permission to change root directory. + *	@path contains the path structure. + *	Return 0 if permission is granted.   * @inode_readlink:   *	Check the permission to read the symbolic link.   *	@dentry contains the dentry structure for the file link. @@ -690,6 +706,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)   * @kernel_module_request:   *	Ability to trigger the kernel to automatically upcall to userspace for   *	userspace to load a kernel module with the given name. + *	@kmod_name name of the module requested by the kernel   *	Return 0 if successful.   * @task_setuid:   *	Check permission before setting one or more of the user identity @@ -1488,6 +1505,10 @@ struct security_operations {  			  struct dentry *new_dentry);  	int (*path_rename) (struct path *old_dir, struct dentry *old_dentry,  			    struct path *new_dir, struct dentry *new_dentry); +	int (*path_chmod) (struct dentry *dentry, struct vfsmount *mnt, +			   mode_t mode); +	int (*path_chown) (struct path *path, uid_t uid, gid_t gid); +	int (*path_chroot) (struct path *path);  #endif  	int (*inode_alloc_security) (struct inode *inode); @@ -1557,7 +1578,7 @@ struct security_operations {  	void (*cred_transfer)(struct cred *new, const struct cred *old);  	int (*kernel_act_as)(struct cred *new, u32 secid);  	int (*kernel_create_files_as)(struct cred *new, struct inode *inode); -	int (*kernel_module_request)(void); +	int (*kernel_module_request)(char *kmod_name);  	int (*task_setuid) (uid_t id0, uid_t id1, uid_t id2, int flags);  	int (*task_fix_setuid) (struct cred *new, const struct cred *old,  				int flags); @@ -1822,7 +1843,7 @@ void security_commit_creds(struct cred *new, const struct cred *old);  void security_transfer_creds(struct cred *new, const struct cred *old);  int security_kernel_act_as(struct cred *new, u32 secid);  int security_kernel_create_files_as(struct cred *new, struct inode *inode); -int security_kernel_module_request(void); +int security_kernel_module_request(char *kmod_name);  int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags);  int security_task_fix_setuid(struct cred *new, const struct cred *old,  			     int flags); @@ -2387,7 +2408,7 @@ static inline int security_kernel_create_files_as(struct cred *cred,  	return 0;  } -static inline int security_kernel_module_request(void) +static inline int security_kernel_module_request(char *kmod_name)  {  	return 0;  } @@ -2952,6 +2973,10 @@ int security_path_link(struct dentry *old_dentry, struct path *new_dir,  		       struct dentry *new_dentry);  int security_path_rename(struct path *old_dir, struct dentry *old_dentry,  			 struct path *new_dir, struct dentry *new_dentry); +int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, +			mode_t mode); +int security_path_chown(struct path *path, uid_t uid, gid_t gid); +int security_path_chroot(struct path *path);  #else	/* CONFIG_SECURITY_PATH */  static inline int security_path_unlink(struct path *dir, struct dentry *dentry)  { @@ -3001,6 +3026,23 @@ static inline int security_path_rename(struct path *old_dir,  {  	return 0;  } + +static inline int security_path_chmod(struct dentry *dentry, +				      struct vfsmount *mnt, +				      mode_t mode) +{ +	return 0; +} + +static inline int security_path_chown(struct path *path, uid_t uid, gid_t gid) +{ +	return 0; +} + +static inline int security_path_chroot(struct path *path) +{ +	return 0; +}  #endif	/* CONFIG_SECURITY_PATH */  #ifdef CONFIG_KEYS diff --git a/include/linux/smp.h b/include/linux/smp.h index 39c64bae776..7a0570e6a59 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -76,6 +76,9 @@ void smp_call_function_many(const struct cpumask *mask,  void __smp_call_function_single(int cpuid, struct call_single_data *data,  				int wait); +int smp_call_function_any(const struct cpumask *mask, +			  void (*func)(void *info), void *info, int wait); +  /*   * Generic and arch helpers   */ @@ -137,9 +140,15 @@ static inline void smp_send_reschedule(int cpu) { }  #define smp_prepare_boot_cpu()			do {} while (0)  #define smp_call_function_many(mask, func, info, wait) \  			(up_smp_call_function(func, info)) -static inline void init_call_single_data(void) +static inline void init_call_single_data(void) { } + +static inline int +smp_call_function_any(const struct cpumask *mask, void (*func)(void *info), +		      void *info, int wait)  { +	return smp_call_function_single(0, func, info, wait);  } +  #endif /* !SMP */  /* diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h index 813be59bf34..2ea1dd1ba21 100644 --- a/include/linux/smp_lock.h +++ b/include/linux/smp_lock.h @@ -24,8 +24,21 @@ static inline int reacquire_kernel_lock(struct task_struct *task)  	return 0;  } -extern void __lockfunc lock_kernel(void)	__acquires(kernel_lock); -extern void __lockfunc unlock_kernel(void)	__releases(kernel_lock); +extern void __lockfunc +_lock_kernel(const char *func, const char *file, int line) +__acquires(kernel_lock); + +extern void __lockfunc +_unlock_kernel(const char *func, const char *file, int line) +__releases(kernel_lock); + +#define lock_kernel() do {					\ +	_lock_kernel(__func__, __FILE__, __LINE__);		\ +} while (0) + +#define unlock_kernel()	do {					\ +	_unlock_kernel(__func__, __FILE__, __LINE__);		\ +} while (0)  /*   * Various legacy drivers don't really need the BKL in a specific @@ -41,8 +54,8 @@ static inline void cycle_kernel_lock(void)  #else -#define lock_kernel()				do { } while(0) -#define unlock_kernel()				do { } while(0) +#define lock_kernel() +#define unlock_kernel()  #define release_kernel_lock(task)		do { } while(0)  #define cycle_kernel_lock()			do { } while(0)  #define reacquire_kernel_lock(task)		0 diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index f0ca7a7a175..71dccfeb0d8 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -79,8 +79,6 @@   */  #include <linux/spinlock_types.h> -extern int __lockfunc generic__raw_read_trylock(raw_rwlock_t *lock); -  /*   * Pull the __raw*() functions/declarations (UP-nondebug doesnt need them):   */ @@ -102,7 +100,7 @@ do {								\  #else  # define spin_lock_init(lock)					\ -	do { *(lock) = SPIN_LOCK_UNLOCKED; } while (0) +	do { *(lock) = __SPIN_LOCK_UNLOCKED(lock); } while (0)  #endif  #ifdef CONFIG_DEBUG_SPINLOCK @@ -116,7 +114,7 @@ do {								\  } while (0)  #else  # define rwlock_init(lock)					\ -	do { *(lock) = RW_LOCK_UNLOCKED; } while (0) +	do { *(lock) = __RW_LOCK_UNLOCKED(lock); } while (0)  #endif  #define spin_is_locked(lock)	__raw_spin_is_locked(&(lock)->raw_lock) diff --git a/include/linux/spinlock_api_smp.h b/include/linux/spinlock_api_smp.h index 7a7e18fc241..8264a7f459b 100644 --- a/include/linux/spinlock_api_smp.h +++ b/include/linux/spinlock_api_smp.h @@ -60,137 +60,118 @@ void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  							__releases(lock); -/* - * We inline the unlock functions in the nondebug case: - */ -#if !defined(CONFIG_DEBUG_SPINLOCK) && !defined(CONFIG_PREEMPT) -#define __always_inline__spin_unlock -#define __always_inline__read_unlock -#define __always_inline__write_unlock -#define __always_inline__spin_unlock_irq -#define __always_inline__read_unlock_irq -#define __always_inline__write_unlock_irq -#endif - -#ifndef CONFIG_DEBUG_SPINLOCK -#ifndef CONFIG_GENERIC_LOCKBREAK - -#ifdef __always_inline__spin_lock +#ifdef CONFIG_INLINE_SPIN_LOCK  #define _spin_lock(lock) __spin_lock(lock)  #endif -#ifdef __always_inline__read_lock +#ifdef CONFIG_INLINE_READ_LOCK  #define _read_lock(lock) __read_lock(lock)  #endif -#ifdef __always_inline__write_lock +#ifdef CONFIG_INLINE_WRITE_LOCK  #define _write_lock(lock) __write_lock(lock)  #endif -#ifdef __always_inline__spin_lock_bh +#ifdef CONFIG_INLINE_SPIN_LOCK_BH  #define _spin_lock_bh(lock) __spin_lock_bh(lock)  #endif -#ifdef __always_inline__read_lock_bh +#ifdef CONFIG_INLINE_READ_LOCK_BH  #define _read_lock_bh(lock) __read_lock_bh(lock)  #endif -#ifdef __always_inline__write_lock_bh +#ifdef CONFIG_INLINE_WRITE_LOCK_BH  #define _write_lock_bh(lock) __write_lock_bh(lock)  #endif -#ifdef __always_inline__spin_lock_irq +#ifdef CONFIG_INLINE_SPIN_LOCK_IRQ  #define _spin_lock_irq(lock) __spin_lock_irq(lock)  #endif -#ifdef __always_inline__read_lock_irq +#ifdef CONFIG_INLINE_READ_LOCK_IRQ  #define _read_lock_irq(lock) __read_lock_irq(lock)  #endif -#ifdef __always_inline__write_lock_irq +#ifdef CONFIG_INLINE_WRITE_LOCK_IRQ  #define _write_lock_irq(lock) __write_lock_irq(lock)  #endif -#ifdef __always_inline__spin_lock_irqsave +#ifdef CONFIG_INLINE_SPIN_LOCK_IRQSAVE  #define _spin_lock_irqsave(lock) __spin_lock_irqsave(lock)  #endif -#ifdef __always_inline__read_lock_irqsave +#ifdef CONFIG_INLINE_READ_LOCK_IRQSAVE  #define _read_lock_irqsave(lock) __read_lock_irqsave(lock)  #endif -#ifdef __always_inline__write_lock_irqsave +#ifdef CONFIG_INLINE_WRITE_LOCK_IRQSAVE  #define _write_lock_irqsave(lock) __write_lock_irqsave(lock)  #endif -#endif /* !CONFIG_GENERIC_LOCKBREAK */ - -#ifdef __always_inline__spin_trylock +#ifdef CONFIG_INLINE_SPIN_TRYLOCK  #define _spin_trylock(lock) __spin_trylock(lock)  #endif -#ifdef __always_inline__read_trylock +#ifdef CONFIG_INLINE_READ_TRYLOCK  #define _read_trylock(lock) __read_trylock(lock)  #endif -#ifdef __always_inline__write_trylock +#ifdef CONFIG_INLINE_WRITE_TRYLOCK  #define _write_trylock(lock) __write_trylock(lock)  #endif -#ifdef __always_inline__spin_trylock_bh +#ifdef CONFIG_INLINE_SPIN_TRYLOCK_BH  #define _spin_trylock_bh(lock) __spin_trylock_bh(lock)  #endif -#ifdef __always_inline__spin_unlock +#ifdef CONFIG_INLINE_SPIN_UNLOCK  #define _spin_unlock(lock) __spin_unlock(lock)  #endif -#ifdef __always_inline__read_unlock +#ifdef CONFIG_INLINE_READ_UNLOCK  #define _read_unlock(lock) __read_unlock(lock)  #endif -#ifdef __always_inline__write_unlock +#ifdef CONFIG_INLINE_WRITE_UNLOCK  #define _write_unlock(lock) __write_unlock(lock)  #endif -#ifdef __always_inline__spin_unlock_bh +#ifdef CONFIG_INLINE_SPIN_UNLOCK_BH  #define _spin_unlock_bh(lock) __spin_unlock_bh(lock)  #endif -#ifdef __always_inline__read_unlock_bh +#ifdef CONFIG_INLINE_READ_UNLOCK_BH  #define _read_unlock_bh(lock) __read_unlock_bh(lock)  #endif -#ifdef __always_inline__write_unlock_bh +#ifdef CONFIG_INLINE_WRITE_UNLOCK_BH  #define _write_unlock_bh(lock) __write_unlock_bh(lock)  #endif -#ifdef __always_inline__spin_unlock_irq +#ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQ  #define _spin_unlock_irq(lock) __spin_unlock_irq(lock)  #endif -#ifdef __always_inline__read_unlock_irq +#ifdef CONFIG_INLINE_READ_UNLOCK_IRQ  #define _read_unlock_irq(lock) __read_unlock_irq(lock)  #endif -#ifdef __always_inline__write_unlock_irq +#ifdef CONFIG_INLINE_WRITE_UNLOCK_IRQ  #define _write_unlock_irq(lock) __write_unlock_irq(lock)  #endif -#ifdef __always_inline__spin_unlock_irqrestore +#ifdef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE  #define _spin_unlock_irqrestore(lock, flags) __spin_unlock_irqrestore(lock, flags)  #endif -#ifdef __always_inline__read_unlock_irqrestore +#ifdef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE  #define _read_unlock_irqrestore(lock, flags) __read_unlock_irqrestore(lock, flags)  #endif -#ifdef __always_inline__write_unlock_irqrestore +#ifdef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE  #define _write_unlock_irqrestore(lock, flags) __write_unlock_irqrestore(lock, flags)  #endif -#endif /* CONFIG_DEBUG_SPINLOCK */ -  static inline int __spin_trylock(spinlock_t *lock)  {  	preempt_disable(); diff --git a/include/linux/srcu.h b/include/linux/srcu.h index aca0eee5393..4765d97dcaf 100644 --- a/include/linux/srcu.h +++ b/include/linux/srcu.h @@ -48,6 +48,7 @@ void cleanup_srcu_struct(struct srcu_struct *sp);  int srcu_read_lock(struct srcu_struct *sp) __acquires(sp);  void srcu_read_unlock(struct srcu_struct *sp, int idx) __releases(sp);  void synchronize_srcu(struct srcu_struct *sp); +void synchronize_srcu_expedited(struct srcu_struct *sp);  long srcu_batches_completed(struct srcu_struct *sp);  #endif diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 73b1f1cec42..febedcf67c7 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h @@ -7,6 +7,8 @@ struct device;  struct dma_attrs;  struct scatterlist; +extern int swiotlb_force; +  /*   * Maximum allowable number of contiguous slabs to map,   * must be a power of 2.  What is the appropriate value ? @@ -20,8 +22,7 @@ struct scatterlist;   */  #define IO_TLB_SHIFT 11 -extern void -swiotlb_init(void); +extern void swiotlb_init(int verbose);  extern void  *swiotlb_alloc_coherent(struct device *hwdev, size_t size, @@ -88,4 +89,11 @@ swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);  extern int  swiotlb_dma_supported(struct device *hwdev, u64 mask); +#ifdef CONFIG_SWIOTLB +extern void __init swiotlb_free(void); +#else +static inline void swiotlb_free(void) { } +#endif + +extern void swiotlb_print_info(void);  #endif /* __LINUX_SWIOTLB_H */ diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 3338b3f5c21..ac5d1c1285d 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -27,9 +27,16 @@   */  #define	TPM_ANY_NUM 0xFFFF -#if defined(CONFIG_TCG_TPM) +#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)  extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);  extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash); +#else +static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) { +	return -ENODEV; +} +static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) { +	return -ENODEV; +}  #endif  #endif diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h index 904468a191e..afc2bfb9e91 100644 --- a/include/pcmcia/cs.h +++ b/include/pcmcia/cs.h @@ -15,6 +15,10 @@  #ifndef _LINUX_CS_H  #define _LINUX_CS_H +#ifdef __KERNEL__ +#include <linux/interrupt.h> +#endif +  /* For AccessConfigurationRegister */  typedef struct conf_reg_t {      u_char	Function; @@ -111,11 +115,9 @@ typedef struct io_req_t {  /* For RequestIRQ and ReleaseIRQ */  typedef struct irq_req_t { -    u_int	Attributes; -    u_int	AssignedIRQ; -    u_int	IRQInfo1, IRQInfo2; /* IRQInfo2 is ignored */ -    void	*Handler; -    void	*Instance; +	u_int		Attributes; +	u_int		AssignedIRQ; +	irq_handler_t	Handler;  } irq_req_t;  /* Attributes for RequestIRQ and ReleaseIRQ */ @@ -125,7 +127,7 @@ typedef struct irq_req_t {  #define IRQ_TYPE_DYNAMIC_SHARING	0x02  #define IRQ_FORCED_PULSE		0x04  #define IRQ_FIRST_SHARED		0x08 -#define IRQ_HANDLE_PRESENT		0x10 +//#define IRQ_HANDLE_PRESENT		0x10  #define IRQ_PULSE_ALLOCATED		0x100  /* Bits in IRQInfo1 field */ diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h index 315965a3793..f5e3b8386c8 100644 --- a/include/pcmcia/cs_types.h +++ b/include/pcmcia/cs_types.h @@ -26,8 +26,7 @@ typedef u_int	event_t;  typedef u_char	cisdata_t;  typedef u_short	page_t; -struct window_t; -typedef struct window_t *window_handle_t; +typedef unsigned long window_handle_t;  struct region_t;  typedef struct region_t *memory_handle_t; diff --git a/include/pcmcia/ds.h b/include/pcmcia/ds.h index a2be80b9a09..d403c12f797 100644 --- a/include/pcmcia/ds.h +++ b/include/pcmcia/ds.h @@ -34,6 +34,7 @@  struct pcmcia_socket;  struct pcmcia_device;  struct config_t; +struct net_device;  /* dynamic device IDs for PCMCIA device drivers. See   * Documentation/pcmcia/driver.txt for details. @@ -137,64 +138,38 @@ struct pcmcia_device {  #define to_pcmcia_dev(n) container_of(n, struct pcmcia_device, dev)  #define to_pcmcia_drv(n) container_of(n, struct pcmcia_driver, drv) -/* deprecated -- don't use! */ -#define handle_to_dev(handle) (handle->dev) - -/* (deprecated) error reporting by PCMCIA devices. Use dev_printk() - * or dev_dbg() directly in the driver, without referring to pcmcia_error_func() - * and/or pcmcia_error_ret() for those functions will go away soon. +/* + * CIS access. + * + * Please use the following functions to access CIS tuples: + * - pcmcia_get_tuple() + * - pcmcia_loop_tuple() + * - pcmcia_get_mac_from_cis() + * + * To parse a tuple_t, pcmcia_parse_tuple() exists. Its interface + * might change in future.   */ -enum service { -    AccessConfigurationRegister, AddSocketServices, -    AdjustResourceInfo, CheckEraseQueue, CloseMemory, CopyMemory, -    DeregisterClient, DeregisterEraseQueue, GetCardServicesInfo, -    GetClientInfo, GetConfigurationInfo, GetEventMask, -    GetFirstClient, GetFirstPartion, GetFirstRegion, GetFirstTuple, -    GetNextClient, GetNextPartition, GetNextRegion, GetNextTuple, -    GetStatus, GetTupleData, MapLogSocket, MapLogWindow, MapMemPage, -    MapPhySocket, MapPhyWindow, ModifyConfiguration, ModifyWindow, -    OpenMemory, ParseTuple, ReadMemory, RegisterClient, -    RegisterEraseQueue, RegisterMTD, RegisterTimer, -    ReleaseConfiguration, ReleaseExclusive, ReleaseIO, ReleaseIRQ, -    ReleaseSocketMask, ReleaseWindow, ReplaceSocketServices, -    RequestConfiguration, RequestExclusive, RequestIO, RequestIRQ, -    RequestSocketMask, RequestWindow, ResetCard, ReturnSSEntry, -    SetEventMask, SetRegion, ValidateCIS, VendorSpecific, -    WriteMemory, BindDevice, BindMTD, ReportError, -    SuspendCard, ResumeCard, EjectCard, InsertCard, ReplaceCIS, -    GetFirstWindow, GetNextWindow, GetMemPage -}; -const char *pcmcia_error_func(int func); -const char *pcmcia_error_ret(int ret); -#define cs_error(p_dev, func, ret)			\ -	{						\ -		dev_printk(KERN_NOTICE, &p_dev->dev,	\ -			   "%s : %s\n",			\ -			   pcmcia_error_func(func),	\ -			   pcmcia_error_ret(ret));	\ -	} +/* get the very first CIS entry of type @code. Note that buf is pointer + * to u8 *buf; and that you need to kfree(buf) afterwards. */ +size_t pcmcia_get_tuple(struct pcmcia_device *p_dev, cisdata_t code, +			u8 **buf); -/* CIS access. - * Use the pcmcia_* versions in PCMCIA drivers - */ -int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse); - -int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, -			   tuple_t *tuple); -#define pcmcia_get_first_tuple(p_dev, tuple) \ -		pccard_get_first_tuple(p_dev->socket, p_dev->func, tuple) +/* loop over CIS entries */ +int pcmcia_loop_tuple(struct pcmcia_device *p_dev, cisdata_t code, +		      int (*loop_tuple) (struct pcmcia_device *p_dev, +					 tuple_t *tuple, +					 void *priv_data), +		      void *priv_data); -int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, -			  tuple_t *tuple); -#define pcmcia_get_next_tuple(p_dev, tuple) \ -		pccard_get_next_tuple(p_dev->socket, p_dev->func, tuple) +/* get the MAC address from CISTPL_FUNCE */ +int pcmcia_get_mac_from_cis(struct pcmcia_device *p_dev, +			    struct net_device *dev); -int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple); -#define pcmcia_get_tuple_data(p_dev, tuple) \ -		pccard_get_tuple_data(p_dev->socket, tuple) +/* parse a tuple_t */ +int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse);  /* loop CIS entries for valid configuration */  int pcmcia_loop_config(struct pcmcia_device *p_dev, @@ -221,12 +196,11 @@ int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req);  int pcmcia_request_configuration(struct pcmcia_device *p_dev,  				 config_req_t *req); -int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, +int pcmcia_request_window(struct pcmcia_device *p_dev, win_req_t *req,  			  window_handle_t *wh); -int pcmcia_release_window(window_handle_t win); - -int pcmcia_get_mem_page(window_handle_t win, memreq_t *req); -int pcmcia_map_mem_page(window_handle_t win, memreq_t *req); +int pcmcia_release_window(struct pcmcia_device *p_dev, window_handle_t win); +int pcmcia_map_mem_page(struct pcmcia_device *p_dev, window_handle_t win, +			memreq_t *req);  int pcmcia_modify_configuration(struct pcmcia_device *p_dev, modconf_t *mod);  void pcmcia_disable_device(struct pcmcia_device *p_dev); diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index e0f6feb8588..7c23be706f1 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h @@ -107,15 +107,6 @@ typedef struct io_window_t {  	struct resource		*res;  } io_window_t; -#define WINDOW_MAGIC	0xB35C -typedef struct window_t { -	u_short			magic; -	u_short			index; -	struct pcmcia_device	*handle; -	struct pcmcia_socket 	*sock; -	pccard_mem_map		ctl; -} window_t; -  /* Maximum number of IO windows per socket */  #define MAX_IO_WIN 2 @@ -155,7 +146,7 @@ struct pcmcia_socket {  		u_int			Config;  	} irq;  	io_window_t			io[MAX_IO_WIN]; -	window_t			win[MAX_WIN]; +	pccard_mem_map			win[MAX_WIN];  	struct list_head		cis_cache;  	size_t				fake_cis_len;  	u8				*fake_cis; @@ -172,7 +163,7 @@ struct pcmcia_socket {  	u_int				irq_mask;  	u_int				map_size;  	u_int				io_offset; -	u_char				pci_irq; +	u_int				pci_irq;  	struct pci_dev *		cb_dev; diff --git a/include/trace/events/bkl.h b/include/trace/events/bkl.h new file mode 100644 index 00000000000..8abd620a490 --- /dev/null +++ b/include/trace/events/bkl.h @@ -0,0 +1,61 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM bkl + +#if !defined(_TRACE_BKL_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_BKL_H + +#include <linux/tracepoint.h> + +TRACE_EVENT(lock_kernel, + +	TP_PROTO(const char *func, const char *file, int line), + +	TP_ARGS(func, file, line), + +	TP_STRUCT__entry( +		__field(	int,		lock_depth		) +		__field_ext(	const char *,	func, FILTER_PTR_STRING	) +		__field_ext(	const char *,	file, FILTER_PTR_STRING	) +		__field(	int,		line			) +	), + +	TP_fast_assign( +		/* We want to record the lock_depth after lock is acquired */ +		__entry->lock_depth = current->lock_depth + 1; +		__entry->func = func; +		__entry->file = file; +		__entry->line = line; +	), + +	TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth, +		  __entry->file, __entry->line, __entry->func) +); + +TRACE_EVENT(unlock_kernel, + +	TP_PROTO(const char *func, const char *file, int line), + +	TP_ARGS(func, file, line), + +	TP_STRUCT__entry( +		__field(int,		lock_depth) +		__field(const char *,	func) +		__field(const char *,	file) +		__field(int,		line) +	), + +	TP_fast_assign( +		__entry->lock_depth = current->lock_depth; +		__entry->func = func; +		__entry->file = file; +		__entry->line = line; +	), + +	TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth, +		  __entry->file, __entry->line, __entry->func) +); + +#endif /* _TRACE_BKL_H */ + +/* This part must be outside protection */ +#include <trace/define_trace.h> diff --git a/include/trace/events/syscalls.h b/include/trace/events/syscalls.h index 397dff2dbd5..fb726ac7cae 100644 --- a/include/trace/events/syscalls.h +++ b/include/trace/events/syscalls.h @@ -1,5 +1,6 @@  #undef TRACE_SYSTEM -#define TRACE_SYSTEM syscalls +#define TRACE_SYSTEM raw_syscalls +#define TRACE_INCLUDE_FILE syscalls  #if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ)  #define _TRACE_EVENTS_SYSCALLS_H diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index cc0d9667e18..dacb8ef6700 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h @@ -159,7 +159,7 @@  #undef __get_str  #undef TP_printk -#define TP_printk(fmt, args...) "%s, %s\n", #fmt, __stringify(args) +#define TP_printk(fmt, args...) "\"%s\", %s\n", fmt, __stringify(args)  #undef TP_fast_assign  #define TP_fast_assign(args...) args diff --git a/include/trace/power.h b/include/trace/power.h deleted file mode 100644 index ef204666e98..00000000000 --- a/include/trace/power.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _TRACE_POWER_H -#define _TRACE_POWER_H - -#include <linux/ktime.h> -#include <linux/tracepoint.h> - -enum { -	POWER_NONE = 0, -	POWER_CSTATE = 1, -	POWER_PSTATE = 2, -}; - -struct power_trace { -	ktime_t			stamp; -	ktime_t			end; -	int			type; -	int			state; -}; - -DECLARE_TRACE(power_start, -	TP_PROTO(struct power_trace *it, unsigned int type, unsigned int state), -	      TP_ARGS(it, type, state)); - -DECLARE_TRACE(power_mark, -	TP_PROTO(struct power_trace *it, unsigned int type, unsigned int state), -	      TP_ARGS(it, type, state)); - -DECLARE_TRACE(power_end, -	TP_PROTO(struct power_trace *it), -	      TP_ARGS(it)); - -#endif /* _TRACE_POWER_H */ diff --git a/include/trace/syscall.h b/include/trace/syscall.h index 5dc283ba5ae..e972f0a40f8 100644 --- a/include/trace/syscall.h +++ b/include/trace/syscall.h @@ -33,7 +33,7 @@ struct syscall_metadata {  };  #ifdef CONFIG_FTRACE_SYSCALLS -extern struct syscall_metadata *syscall_nr_to_meta(int nr); +extern unsigned long arch_syscall_addr(int nr);  extern int syscall_name_to_nr(char *name);  void set_syscall_enter_id(int num, int id);  void set_syscall_exit_id(int num, int id); diff --git a/init/Kconfig b/init/Kconfig index 39923ccc287..9ee77829475 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -334,6 +334,15 @@ config TREE_PREEMPT_RCU  	  is also required.  It also scales down nicely to  	  smaller systems. +config TINY_RCU +	bool "UP-only small-memory-footprint RCU" +	depends on !SMP +	help +	  This option selects the RCU implementation that is +	  designed for UP systems from which real-time response +	  is not required.  This option greatly reduces the +	  memory footprint of RCU. +  endchoice  config RCU_TRACE @@ -606,7 +615,7 @@ config SYSFS_DEPRECATED  	bool  config SYSFS_DEPRECATED_V2 -	bool "remove sysfs features which may confuse old userspace tools" +	bool "enable deprecated sysfs features which may confuse old userspace tools"  	depends on SYSFS  	default n  	select SYSFS_DEPRECATED @@ -1220,3 +1229,4 @@ source "block/Kconfig"  config PREEMPT_NOTIFIERS  	bool +source "kernel/Kconfig.locks" diff --git a/init/main.c b/init/main.c index 5988debfc50..4051d75dd2d 100644 --- a/init/main.c +++ b/init/main.c @@ -251,7 +251,7 @@ early_param("loglevel", loglevel);  /*   * Unknown boot options get handed to init, unless they look like - * failed parameters + * unused parameters (modprobe will find them in /proc/cmdline).   */  static int __init unknown_bootoption(char *param, char *val)  { @@ -272,14 +272,9 @@ static int __init unknown_bootoption(char *param, char *val)  	if (obsolete_checksetup(param))  		return 0; -	/* -	 * Preemptive maintenance for "why didn't my misspelled command -	 * line work?" -	 */ -	if (strchr(param, '.') && (!val || strchr(param, '.') < val)) { -		printk(KERN_ERR "Unknown boot option `%s': ignoring\n", param); +	/* Unused module parameter. */ +	if (strchr(param, '.') && (!val || strchr(param, '.') < val))  		return 0; -	}  	if (panic_later)  		return 0; diff --git a/kernel/Kconfig.locks b/kernel/Kconfig.locks new file mode 100644 index 00000000000..88c92fb4461 --- /dev/null +++ b/kernel/Kconfig.locks @@ -0,0 +1,202 @@ +# +# The ARCH_INLINE foo is necessary because select ignores "depends on" +# +config ARCH_INLINE_SPIN_TRYLOCK +	bool + +config ARCH_INLINE_SPIN_TRYLOCK_BH +	bool + +config ARCH_INLINE_SPIN_LOCK +	bool + +config ARCH_INLINE_SPIN_LOCK_BH +	bool + +config ARCH_INLINE_SPIN_LOCK_IRQ +	bool + +config ARCH_INLINE_SPIN_LOCK_IRQSAVE +	bool + +config ARCH_INLINE_SPIN_UNLOCK +	bool + +config ARCH_INLINE_SPIN_UNLOCK_BH +	bool + +config ARCH_INLINE_SPIN_UNLOCK_IRQ +	bool + +config ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE +	bool + + +config ARCH_INLINE_READ_TRYLOCK +	bool + +config ARCH_INLINE_READ_LOCK +	bool + +config ARCH_INLINE_READ_LOCK_BH +	bool + +config ARCH_INLINE_READ_LOCK_IRQ +	bool + +config ARCH_INLINE_READ_LOCK_IRQSAVE +	bool + +config ARCH_INLINE_READ_UNLOCK +	bool + +config ARCH_INLINE_READ_UNLOCK_BH +	bool + +config ARCH_INLINE_READ_UNLOCK_IRQ +	bool + +config ARCH_INLINE_READ_UNLOCK_IRQRESTORE +	bool + + +config ARCH_INLINE_WRITE_TRYLOCK +	bool + +config ARCH_INLINE_WRITE_LOCK +	bool + +config ARCH_INLINE_WRITE_LOCK_BH +	bool + +config ARCH_INLINE_WRITE_LOCK_IRQ +	bool + +config ARCH_INLINE_WRITE_LOCK_IRQSAVE +	bool + +config ARCH_INLINE_WRITE_UNLOCK +	bool + +config ARCH_INLINE_WRITE_UNLOCK_BH +	bool + +config ARCH_INLINE_WRITE_UNLOCK_IRQ +	bool + +config ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE +	bool + +# +# lock_* functions are inlined when: +#   - DEBUG_SPINLOCK=n and GENERIC_LOCKBREAK=n and ARCH_INLINE_*LOCK=y +# +# trylock_* functions are inlined when: +#   - DEBUG_SPINLOCK=n and ARCH_INLINE_*LOCK=y +# +# unlock and unlock_irq functions are inlined when: +#   - DEBUG_SPINLOCK=n and ARCH_INLINE_*LOCK=y +#  or +#   - DEBUG_SPINLOCK=n and PREEMPT=n +# +# unlock_bh and unlock_irqrestore functions are inlined when: +#   - DEBUG_SPINLOCK=n and ARCH_INLINE_*LOCK=y +# + +config INLINE_SPIN_TRYLOCK +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_TRYLOCK + +config INLINE_SPIN_TRYLOCK_BH +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_TRYLOCK_BH + +config INLINE_SPIN_LOCK +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && ARCH_INLINE_SPIN_LOCK + +config INLINE_SPIN_LOCK_BH +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_SPIN_LOCK_BH + +config INLINE_SPIN_LOCK_IRQ +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_SPIN_LOCK_IRQ + +config INLINE_SPIN_LOCK_IRQSAVE +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_SPIN_LOCK_IRQSAVE + +config INLINE_SPIN_UNLOCK +	def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_SPIN_UNLOCK) + +config INLINE_SPIN_UNLOCK_BH +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_UNLOCK_BH + +config INLINE_SPIN_UNLOCK_IRQ +	def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_SPIN_UNLOCK_BH) + +config INLINE_SPIN_UNLOCK_IRQRESTORE +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE + + +config INLINE_READ_TRYLOCK +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_READ_TRYLOCK + +config INLINE_READ_LOCK +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && ARCH_INLINE_READ_LOCK + +config INLINE_READ_LOCK_BH +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_READ_LOCK_BH + +config INLINE_READ_LOCK_IRQ +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_READ_LOCK_IRQ + +config INLINE_READ_LOCK_IRQSAVE +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_READ_LOCK_IRQSAVE + +config INLINE_READ_UNLOCK +	def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_READ_UNLOCK) + +config INLINE_READ_UNLOCK_BH +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_READ_UNLOCK_BH + +config INLINE_READ_UNLOCK_IRQ +	def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_READ_UNLOCK_BH) + +config INLINE_READ_UNLOCK_IRQRESTORE +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_READ_UNLOCK_IRQRESTORE + + +config INLINE_WRITE_TRYLOCK +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_WRITE_TRYLOCK + +config INLINE_WRITE_LOCK +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && ARCH_INLINE_WRITE_LOCK + +config INLINE_WRITE_LOCK_BH +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_WRITE_LOCK_BH + +config INLINE_WRITE_LOCK_IRQ +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_WRITE_LOCK_IRQ + +config INLINE_WRITE_LOCK_IRQSAVE +	def_bool !DEBUG_SPINLOCK && !GENERIC_LOCKBREAK && \ +		 ARCH_INLINE_WRITE_LOCK_IRQSAVE + +config INLINE_WRITE_UNLOCK +	def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_WRITE_UNLOCK) + +config INLINE_WRITE_UNLOCK_BH +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_WRITE_UNLOCK_BH + +config INLINE_WRITE_UNLOCK_IRQ +	def_bool !DEBUG_SPINLOCK && (!PREEMPT || ARCH_INLINE_WRITE_UNLOCK_BH) + +config INLINE_WRITE_UNLOCK_IRQRESTORE +	def_bool !DEBUG_SPINLOCK && ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE + +config MUTEX_SPIN_ON_OWNER +	def_bool SMP && !DEBUG_MUTEXES && !HAVE_DEFAULT_NO_SPIN_MUTEXES diff --git a/kernel/Makefile b/kernel/Makefile index d7c13d249b2..dcf6789bf54 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -82,6 +82,7 @@ obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o  obj-$(CONFIG_TREE_RCU) += rcutree.o  obj-$(CONFIG_TREE_PREEMPT_RCU) += rcutree.o  obj-$(CONFIG_TREE_RCU_TRACE) += rcutree_trace.o +obj-$(CONFIG_TINY_RCU) += rcutiny.o  obj-$(CONFIG_RELAY) += relay.o  obj-$(CONFIG_SYSCTL) += utsname_sysctl.o  obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o diff --git a/kernel/capability.c b/kernel/capability.c index 4e17041963f..7f876e60521 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -29,7 +29,6 @@ EXPORT_SYMBOL(__cap_empty_set);  EXPORT_SYMBOL(__cap_full_set);  EXPORT_SYMBOL(__cap_init_eff_set); -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  int file_caps_enabled = 1;  static int __init file_caps_disable(char *str) @@ -38,7 +37,6 @@ static int __init file_caps_disable(char *str)  	return 1;  }  __setup("no_file_caps", file_caps_disable); -#endif  /*   * More recent versions of libcap are available from: @@ -169,8 +167,8 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)  	kernel_cap_t pE, pI, pP;  	ret = cap_validate_magic(header, &tocopy); -	if (ret != 0) -		return ret; +	if ((dataptr == NULL) || (ret != 0)) +		return ((dataptr == NULL) && (ret == -EINVAL)) ? 0 : ret;  	if (get_user(pid, &header->pid))  		return -EFAULT; @@ -238,7 +236,7 @@ SYSCALL_DEFINE2(capget, cap_user_header_t, header, cap_user_data_t, dataptr)  SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)  {  	struct __user_cap_data_struct kdata[_KERNEL_CAPABILITY_U32S]; -	unsigned i, tocopy; +	unsigned i, tocopy, copybytes;  	kernel_cap_t inheritable, permitted, effective;  	struct cred *new;  	int ret; @@ -255,8 +253,11 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)  	if (pid != 0 && pid != task_pid_vnr(current))  		return -EPERM; -	if (copy_from_user(&kdata, data, -			   tocopy * sizeof(struct __user_cap_data_struct))) +	copybytes = tocopy * sizeof(struct __user_cap_data_struct); +	if (copybytes > sizeof(kdata)) +		return -EFAULT; + +	if (copy_from_user(&kdata, data, copybytes))  		return -EFAULT;  	for (i = 0; i < tocopy; i++) { diff --git a/kernel/hung_task.c b/kernel/hung_task.c index d4e84174740..0c642d51aac 100644 --- a/kernel/hung_task.c +++ b/kernel/hung_task.c @@ -144,7 +144,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)  	rcu_read_lock();  	do_each_thread(g, t) { -		if (!--max_count) +		if (!max_count--)  			goto unlock;  		if (!--batch_count) {  			batch_count = HUNG_TASK_BATCHING; diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c index c1660194d11..ba566c261ad 100644 --- a/kernel/irq/chip.c +++ b/kernel/irq/chip.c @@ -166,11 +166,11 @@ int set_irq_data(unsigned int irq, void *data)  EXPORT_SYMBOL(set_irq_data);  /** - *	set_irq_data - set irq type data for an irq + *	set_irq_msi - set MSI descriptor data for an irq   *	@irq:	Interrupt number   *	@entry:	Pointer to MSI descriptor data   * - *	Set the hardware irq controller data for an irq + *	Set the MSI descriptor entry for an irq   */  int set_irq_msi(unsigned int irq, struct msi_desc *entry)  { @@ -590,7 +590,7 @@ out_unlock:  }  /** - *	handle_percpu_IRQ - Per CPU local irq handler + *	handle_percpu_irq - Per CPU local irq handler   *	@irq:	the interrupt number   *	@desc:	the interrupt description structure for this irq   * diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 692363dd591..0832145fea9 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -136,7 +136,7 @@ out:  static int default_affinity_open(struct inode *inode, struct file *file)  { -	return single_open(file, default_affinity_show, NULL); +	return single_open(file, default_affinity_show, PDE(inode)->data);  }  static const struct file_operations default_affinity_proc_fops = { @@ -148,18 +148,28 @@ static const struct file_operations default_affinity_proc_fops = {  };  #endif -static int irq_spurious_read(char *page, char **start, off_t off, -				  int count, int *eof, void *data) +static int irq_spurious_proc_show(struct seq_file *m, void *v)  { -	struct irq_desc *desc = irq_to_desc((long) data); -	return sprintf(page, "count %u\n" -			     "unhandled %u\n" -			     "last_unhandled %u ms\n", -			desc->irq_count, -			desc->irqs_unhandled, -			jiffies_to_msecs(desc->last_unhandled)); +	struct irq_desc *desc = irq_to_desc((long) m->private); + +	seq_printf(m, "count %u\n" "unhandled %u\n" "last_unhandled %u ms\n", +		   desc->irq_count, desc->irqs_unhandled, +		   jiffies_to_msecs(desc->last_unhandled)); +	return 0; +} + +static int irq_spurious_proc_open(struct inode *inode, struct file *file) +{ +	return single_open(file, irq_spurious_proc_show, NULL);  } +static const struct file_operations irq_spurious_proc_fops = { +	.open		= irq_spurious_proc_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= single_release, +}; +  #define MAX_NAMELEN 128  static int name_unique(unsigned int irq, struct irqaction *new_action) @@ -204,7 +214,6 @@ void register_handler_proc(unsigned int irq, struct irqaction *action)  void register_irq_proc(unsigned int irq, struct irq_desc *desc)  {  	char name [MAX_NAMELEN]; -	struct proc_dir_entry *entry;  	if (!root_irq_dir || (desc->chip == &no_irq_chip) || desc->dir)  		return; @@ -214,6 +223,8 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)  	/* create /proc/irq/1234 */  	desc->dir = proc_mkdir(name, root_irq_dir); +	if (!desc->dir) +		return;  #ifdef CONFIG_SMP  	/* create /proc/irq/<irq>/smp_affinity */ @@ -221,11 +232,8 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)  			 &irq_affinity_proc_fops, (void *)(long)irq);  #endif -	entry = create_proc_entry("spurious", 0444, desc->dir); -	if (entry) { -		entry->data = (void *)(long)irq; -		entry->read_proc = irq_spurious_read; -	} +	proc_create_data("spurious", 0444, desc->dir, +			 &irq_spurious_proc_fops, (void *)(long)irq);  }  #undef MAX_NAMELEN diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index bd7273e6282..22b0a6eedf2 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -104,7 +104,7 @@ static int misrouted_irq(int irq)  	return ok;  } -static void poll_all_shared_irqs(void) +static void poll_spurious_irqs(unsigned long dummy)  {  	struct irq_desc *desc;  	int i; @@ -125,23 +125,11 @@ static void poll_all_shared_irqs(void)  		try_one_irq(i, desc);  		local_irq_enable();  	} -} - -static void poll_spurious_irqs(unsigned long dummy) -{ -	poll_all_shared_irqs();  	mod_timer(&poll_spurious_irq_timer,  		  jiffies + POLL_SPURIOUS_IRQ_INTERVAL);  } -#ifdef CONFIG_DEBUG_SHIRQ -void debug_poll_all_shared_irqs(void) -{ -	poll_all_shared_irqs(); -} -#endif -  /*   * If 99,900 of the previous 100,000 interrupts have not been handled   * then assume that the IRQ is stuck in some manner. Drop a diagnostic diff --git a/kernel/kmod.c b/kernel/kmod.c index 9fcb53a11f8..25b10319036 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -80,16 +80,16 @@ int __request_module(bool wait, const char *fmt, ...)  #define MAX_KMOD_CONCURRENT 50	/* Completely arbitrary value - KAO */  	static int kmod_loop_msg; -	ret = security_kernel_module_request(); -	if (ret) -		return ret; -  	va_start(args, fmt);  	ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);  	va_end(args);  	if (ret >= MODULE_NAME_LEN)  		return -ENAMETOOLONG; +	ret = security_kernel_module_request(module_name); +	if (ret) +		return ret; +  	/* If modprobe needs a service that is in a module, we get a recursive  	 * loop.  Limit the number of running kmod threads to max_threads/2 or  	 * MAX_KMOD_CONCURRENT, whichever is the smaller.  A cleaner method diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 5240d75f4c6..1494e85b35f 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1014,9 +1014,9 @@ int __kprobes register_kretprobe(struct kretprobe *rp)  	/* Pre-allocate memory for max kretprobe instances */  	if (rp->maxactive <= 0) {  #ifdef CONFIG_PREEMPT -		rp->maxactive = max(10, 2 * NR_CPUS); +		rp->maxactive = max(10, 2 * num_possible_cpus());  #else -		rp->maxactive = NR_CPUS; +		rp->maxactive = num_possible_cpus();  #endif  	}  	spin_lock_init(&rp->lock); diff --git a/kernel/module.c b/kernel/module.c index 8b7d8805819..5842a71cf05 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -1187,7 +1187,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,  	/* Count loaded sections and allocate structures */  	for (i = 0; i < nsect; i++) -		if (sechdrs[i].sh_flags & SHF_ALLOC) +		if (sechdrs[i].sh_flags & SHF_ALLOC +		    && sechdrs[i].sh_size)  			nloaded++;  	size[0] = ALIGN(sizeof(*sect_attrs)  			+ nloaded * sizeof(sect_attrs->attrs[0]), @@ -1207,6 +1208,8 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,  	for (i = 0; i < nsect; i++) {  		if (! (sechdrs[i].sh_flags & SHF_ALLOC))  			continue; +		if (!sechdrs[i].sh_size) +			continue;  		sattr->address = sechdrs[i].sh_addr;  		sattr->name = kstrdup(secstrings + sechdrs[i].sh_name,  					GFP_KERNEL); diff --git a/kernel/mutex.c b/kernel/mutex.c index 947b3ad551f..632f04c57d8 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -148,8 +148,8 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,  	preempt_disable();  	mutex_acquire(&lock->dep_map, subclass, 0, ip); -#if defined(CONFIG_SMP) && !defined(CONFIG_DEBUG_MUTEXES) && \ -    !defined(CONFIG_HAVE_DEFAULT_NO_SPIN_MUTEXES) + +#ifdef CONFIG_MUTEX_SPIN_ON_OWNER  	/*  	 * Optimistic spinning.  	 * diff --git a/kernel/printk.c b/kernel/printk.c index f38b07f78a4..b5ac4d99c66 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -33,6 +33,7 @@  #include <linux/bootmem.h>  #include <linux/syscalls.h>  #include <linux/kexec.h> +#include <linux/ratelimit.h>  #include <asm/uaccess.h> @@ -1376,11 +1377,11 @@ late_initcall(disable_boot_consoles);   */  DEFINE_RATELIMIT_STATE(printk_ratelimit_state, 5 * HZ, 10); -int printk_ratelimit(void) +int __printk_ratelimit(const char *func)  { -	return __ratelimit(&printk_ratelimit_state); +	return ___ratelimit(&printk_ratelimit_state, func);  } -EXPORT_SYMBOL(printk_ratelimit); +EXPORT_SYMBOL(__printk_ratelimit);  /**   * printk_timed_ratelimit - caller-controlled printk ratelimiting diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 400183346ad..9b7fd472387 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -44,7 +44,6 @@  #include <linux/cpu.h>  #include <linux/mutex.h>  #include <linux/module.h> -#include <linux/kernel_stat.h>  #ifdef CONFIG_DEBUG_LOCK_ALLOC  static struct lock_class_key rcu_lock_key; @@ -53,8 +52,6 @@ struct lockdep_map rcu_lock_map =  EXPORT_SYMBOL_GPL(rcu_lock_map);  #endif -int rcu_scheduler_active __read_mostly; -  /*   * Awaken the corresponding synchronize_rcu() instance now that a   * grace period has elapsed. @@ -66,122 +63,3 @@ void wakeme_after_rcu(struct rcu_head  *head)  	rcu = container_of(head, struct rcu_synchronize, head);  	complete(&rcu->completion);  } - -#ifdef CONFIG_TREE_PREEMPT_RCU - -/** - * synchronize_rcu - wait until a grace period has elapsed. - * - * Control will return to the caller some time after a full grace - * period has elapsed, in other words after all currently executing RCU - * read-side critical sections have completed.  RCU read-side critical - * sections are delimited by rcu_read_lock() and rcu_read_unlock(), - * and may be nested. - */ -void synchronize_rcu(void) -{ -	struct rcu_synchronize rcu; - -	if (!rcu_scheduler_active) -		return; - -	init_completion(&rcu.completion); -	/* Will wake me after RCU finished. */ -	call_rcu(&rcu.head, wakeme_after_rcu); -	/* Wait for it. */ -	wait_for_completion(&rcu.completion); -} -EXPORT_SYMBOL_GPL(synchronize_rcu); - -#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */ - -/** - * synchronize_sched - wait until an rcu-sched grace period has elapsed. - * - * Control will return to the caller some time after a full rcu-sched - * grace period has elapsed, in other words after all currently executing - * rcu-sched read-side critical sections have completed.   These read-side - * critical sections are delimited by rcu_read_lock_sched() and - * rcu_read_unlock_sched(), and may be nested.  Note that preempt_disable(), - * local_irq_disable(), and so on may be used in place of - * rcu_read_lock_sched(). - * - * This means that all preempt_disable code sequences, including NMI and - * hardware-interrupt handlers, in progress on entry will have completed - * before this primitive returns.  However, this does not guarantee that - * softirq handlers will have completed, since in some kernels, these - * handlers can run in process context, and can block. - * - * This primitive provides the guarantees made by the (now removed) - * synchronize_kernel() API.  In contrast, synchronize_rcu() only - * guarantees that rcu_read_lock() sections will have completed. - * In "classic RCU", these two guarantees happen to be one and - * the same, but can differ in realtime RCU implementations. - */ -void synchronize_sched(void) -{ -	struct rcu_synchronize rcu; - -	if (rcu_blocking_is_gp()) -		return; - -	init_completion(&rcu.completion); -	/* Will wake me after RCU finished. */ -	call_rcu_sched(&rcu.head, wakeme_after_rcu); -	/* Wait for it. */ -	wait_for_completion(&rcu.completion); -} -EXPORT_SYMBOL_GPL(synchronize_sched); - -/** - * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed. - * - * Control will return to the caller some time after a full rcu_bh grace - * period has elapsed, in other words after all currently executing rcu_bh - * read-side critical sections have completed.  RCU read-side critical - * sections are delimited by rcu_read_lock_bh() and rcu_read_unlock_bh(), - * and may be nested. - */ -void synchronize_rcu_bh(void) -{ -	struct rcu_synchronize rcu; - -	if (rcu_blocking_is_gp()) -		return; - -	init_completion(&rcu.completion); -	/* Will wake me after RCU finished. */ -	call_rcu_bh(&rcu.head, wakeme_after_rcu); -	/* Wait for it. */ -	wait_for_completion(&rcu.completion); -} -EXPORT_SYMBOL_GPL(synchronize_rcu_bh); - -static int __cpuinit rcu_barrier_cpu_hotplug(struct notifier_block *self, -		unsigned long action, void *hcpu) -{ -	return rcu_cpu_notify(self, action, hcpu); -} - -void __init rcu_init(void) -{ -	int i; - -	__rcu_init(); -	cpu_notifier(rcu_barrier_cpu_hotplug, 0); - -	/* -	 * We don't need protection against CPU-hotplug here because -	 * this is called early in boot, before either interrupts -	 * or the scheduler are operational. -	 */ -	for_each_online_cpu(i) -		rcu_barrier_cpu_hotplug(NULL, CPU_UP_PREPARE, (void *)(long)i); -} - -void rcu_scheduler_starting(void) -{ -	WARN_ON(num_online_cpus() != 1); -	WARN_ON(nr_context_switches() > 0); -	rcu_scheduler_active = 1; -} diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c new file mode 100644 index 00000000000..9f6d9ff2572 --- /dev/null +++ b/kernel/rcutiny.c @@ -0,0 +1,282 @@ +/* + * Read-Copy Update mechanism for mutual exclusion, the Bloatwatch edition. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright IBM Corporation, 2008 + * + * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com> + * + * For detailed explanation of Read-Copy Update mechanism see - + *		Documentation/RCU + */ +#include <linux/moduleparam.h> +#include <linux/completion.h> +#include <linux/interrupt.h> +#include <linux/notifier.h> +#include <linux/rcupdate.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/time.h> +#include <linux/cpu.h> + +/* Global control variables for rcupdate callback mechanism. */ +struct rcu_ctrlblk { +	struct rcu_head *rcucblist;	/* List of pending callbacks (CBs). */ +	struct rcu_head **donetail;	/* ->next pointer of last "done" CB. */ +	struct rcu_head **curtail;	/* ->next pointer of last CB. */ +}; + +/* Definition for rcupdate control block. */ +static struct rcu_ctrlblk rcu_ctrlblk = { +	.donetail	= &rcu_ctrlblk.rcucblist, +	.curtail	= &rcu_ctrlblk.rcucblist, +}; + +static struct rcu_ctrlblk rcu_bh_ctrlblk = { +	.donetail	= &rcu_bh_ctrlblk.rcucblist, +	.curtail	= &rcu_bh_ctrlblk.rcucblist, +}; + +#ifdef CONFIG_NO_HZ + +static long rcu_dynticks_nesting = 1; + +/* + * Enter dynticks-idle mode, which is an extended quiescent state + * if we have fully entered that mode (i.e., if the new value of + * dynticks_nesting is zero). + */ +void rcu_enter_nohz(void) +{ +	if (--rcu_dynticks_nesting == 0) +		rcu_sched_qs(0); /* implies rcu_bh_qsctr_inc(0) */ +} + +/* + * Exit dynticks-idle mode, so that we are no longer in an extended + * quiescent state. + */ +void rcu_exit_nohz(void) +{ +	rcu_dynticks_nesting++; +} + +#endif /* #ifdef CONFIG_NO_HZ */ + +/* + * Helper function for rcu_qsctr_inc() and rcu_bh_qsctr_inc(). + * Also disable irqs to avoid confusion due to interrupt handlers + * invoking call_rcu(). + */ +static int rcu_qsctr_help(struct rcu_ctrlblk *rcp) +{ +	unsigned long flags; + +	local_irq_save(flags); +	if (rcp->rcucblist != NULL && +	    rcp->donetail != rcp->curtail) { +		rcp->donetail = rcp->curtail; +		local_irq_restore(flags); +		return 1; +	} +	local_irq_restore(flags); + +	return 0; +} + +/* + * Record an rcu quiescent state.  And an rcu_bh quiescent state while we + * are at it, given that any rcu quiescent state is also an rcu_bh + * quiescent state.  Use "+" instead of "||" to defeat short circuiting. + */ +void rcu_sched_qs(int cpu) +{ +	if (rcu_qsctr_help(&rcu_ctrlblk) + rcu_qsctr_help(&rcu_bh_ctrlblk)) +		raise_softirq(RCU_SOFTIRQ); +} + +/* + * Record an rcu_bh quiescent state. + */ +void rcu_bh_qs(int cpu) +{ +	if (rcu_qsctr_help(&rcu_bh_ctrlblk)) +		raise_softirq(RCU_SOFTIRQ); +} + +/* + * Check to see if the scheduling-clock interrupt came from an extended + * quiescent state, and, if so, tell RCU about it. + */ +void rcu_check_callbacks(int cpu, int user) +{ +	if (user || +	    (idle_cpu(cpu) && +	     !in_softirq() && +	     hardirq_count() <= (1 << HARDIRQ_SHIFT))) +		rcu_sched_qs(cpu); +	else if (!in_softirq()) +		rcu_bh_qs(cpu); +} + +/* + * Helper function for rcu_process_callbacks() that operates on the + * specified rcu_ctrlkblk structure. + */ +static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp) +{ +	struct rcu_head *next, *list; +	unsigned long flags; + +	/* If no RCU callbacks ready to invoke, just return. */ +	if (&rcp->rcucblist == rcp->donetail) +		return; + +	/* Move the ready-to-invoke callbacks to a local list. */ +	local_irq_save(flags); +	list = rcp->rcucblist; +	rcp->rcucblist = *rcp->donetail; +	*rcp->donetail = NULL; +	if (rcp->curtail == rcp->donetail) +		rcp->curtail = &rcp->rcucblist; +	rcp->donetail = &rcp->rcucblist; +	local_irq_restore(flags); + +	/* Invoke the callbacks on the local list. */ +	while (list) { +		next = list->next; +		prefetch(next); +		list->func(list); +		list = next; +	} +} + +/* + * Invoke any callbacks whose grace period has completed. + */ +static void rcu_process_callbacks(struct softirq_action *unused) +{ +	__rcu_process_callbacks(&rcu_ctrlblk); +	__rcu_process_callbacks(&rcu_bh_ctrlblk); +} + +/* + * Wait for a grace period to elapse.  But it is illegal to invoke + * synchronize_sched() from within an RCU read-side critical section. + * Therefore, any legal call to synchronize_sched() is a quiescent + * state, and so on a UP system, synchronize_sched() need do nothing. + * Ditto for synchronize_rcu_bh().  (But Lai Jiangshan points out the + * benefits of doing might_sleep() to reduce latency.) + * + * Cool, huh?  (Due to Josh Triplett.) + * + * But we want to make this a static inline later. + */ +void synchronize_sched(void) +{ +	cond_resched(); +} +EXPORT_SYMBOL_GPL(synchronize_sched); + +void synchronize_rcu_bh(void) +{ +	synchronize_sched(); +} +EXPORT_SYMBOL_GPL(synchronize_rcu_bh); + +/* + * Helper function for call_rcu() and call_rcu_bh(). + */ +static void __call_rcu(struct rcu_head *head, +		       void (*func)(struct rcu_head *rcu), +		       struct rcu_ctrlblk *rcp) +{ +	unsigned long flags; + +	head->func = func; +	head->next = NULL; + +	local_irq_save(flags); +	*rcp->curtail = head; +	rcp->curtail = &head->next; +	local_irq_restore(flags); +} + +/* + * Post an RCU callback to be invoked after the end of an RCU grace + * period.  But since we have but one CPU, that would be after any + * quiescent state. + */ +void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) +{ +	__call_rcu(head, func, &rcu_ctrlblk); +} +EXPORT_SYMBOL_GPL(call_rcu); + +/* + * Post an RCU bottom-half callback to be invoked after any subsequent + * quiescent state. + */ +void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu)) +{ +	__call_rcu(head, func, &rcu_bh_ctrlblk); +} +EXPORT_SYMBOL_GPL(call_rcu_bh); + +void rcu_barrier(void) +{ +	struct rcu_synchronize rcu; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +} +EXPORT_SYMBOL_GPL(rcu_barrier); + +void rcu_barrier_bh(void) +{ +	struct rcu_synchronize rcu; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu_bh(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +} +EXPORT_SYMBOL_GPL(rcu_barrier_bh); + +void rcu_barrier_sched(void) +{ +	struct rcu_synchronize rcu; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu_sched(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +} +EXPORT_SYMBOL_GPL(rcu_barrier_sched); + +void __init rcu_init(void) +{ +	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); +} diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index 697c0a0229d..a621a67ef4e 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -327,6 +327,11 @@ rcu_torture_cb(struct rcu_head *p)  		cur_ops->deferred_free(rp);  } +static int rcu_no_completed(void) +{ +	return 0; +} +  static void rcu_torture_deferred_free(struct rcu_torture *p)  {  	call_rcu(&p->rtort_rcu, rcu_torture_cb); @@ -388,6 +393,21 @@ static struct rcu_torture_ops rcu_sync_ops = {  	.name		= "rcu_sync"  }; +static struct rcu_torture_ops rcu_expedited_ops = { +	.init		= rcu_sync_torture_init, +	.cleanup	= NULL, +	.readlock	= rcu_torture_read_lock, +	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */ +	.readunlock	= rcu_torture_read_unlock, +	.completed	= rcu_no_completed, +	.deferred_free	= rcu_sync_torture_deferred_free, +	.sync		= synchronize_rcu_expedited, +	.cb_barrier	= NULL, +	.stats		= NULL, +	.irq_capable	= 1, +	.name		= "rcu_expedited" +}; +  /*   * Definitions for rcu_bh torture testing.   */ @@ -547,6 +567,25 @@ static struct rcu_torture_ops srcu_ops = {  	.name		= "srcu"  }; +static void srcu_torture_synchronize_expedited(void) +{ +	synchronize_srcu_expedited(&srcu_ctl); +} + +static struct rcu_torture_ops srcu_expedited_ops = { +	.init		= srcu_torture_init, +	.cleanup	= srcu_torture_cleanup, +	.readlock	= srcu_torture_read_lock, +	.read_delay	= srcu_read_delay, +	.readunlock	= srcu_torture_read_unlock, +	.completed	= srcu_torture_completed, +	.deferred_free	= rcu_sync_torture_deferred_free, +	.sync		= srcu_torture_synchronize_expedited, +	.cb_barrier	= NULL, +	.stats		= srcu_torture_stats, +	.name		= "srcu_expedited" +}; +  /*   * Definitions for sched torture testing.   */ @@ -562,11 +601,6 @@ static void sched_torture_read_unlock(int idx)  	preempt_enable();  } -static int sched_torture_completed(void) -{ -	return 0; -} -  static void rcu_sched_torture_deferred_free(struct rcu_torture *p)  {  	call_rcu_sched(&p->rtort_rcu, rcu_torture_cb); @@ -583,7 +617,7 @@ static struct rcu_torture_ops sched_ops = {  	.readlock	= sched_torture_read_lock,  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */  	.readunlock	= sched_torture_read_unlock, -	.completed	= sched_torture_completed, +	.completed	= rcu_no_completed,  	.deferred_free	= rcu_sched_torture_deferred_free,  	.sync		= sched_torture_synchronize,  	.cb_barrier	= rcu_barrier_sched, @@ -592,13 +626,13 @@ static struct rcu_torture_ops sched_ops = {  	.name		= "sched"  }; -static struct rcu_torture_ops sched_ops_sync = { +static struct rcu_torture_ops sched_sync_ops = {  	.init		= rcu_sync_torture_init,  	.cleanup	= NULL,  	.readlock	= sched_torture_read_lock,  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */  	.readunlock	= sched_torture_read_unlock, -	.completed	= sched_torture_completed, +	.completed	= rcu_no_completed,  	.deferred_free	= rcu_sync_torture_deferred_free,  	.sync		= sched_torture_synchronize,  	.cb_barrier	= NULL, @@ -612,7 +646,7 @@ static struct rcu_torture_ops sched_expedited_ops = {  	.readlock	= sched_torture_read_lock,  	.read_delay	= rcu_read_delay,  /* just reuse rcu's version. */  	.readunlock	= sched_torture_read_unlock, -	.completed	= sched_torture_completed, +	.completed	= rcu_no_completed,  	.deferred_free	= rcu_sync_torture_deferred_free,  	.sync		= synchronize_sched_expedited,  	.cb_barrier	= NULL, @@ -1097,9 +1131,10 @@ rcu_torture_init(void)  	int cpu;  	int firsterr = 0;  	static struct rcu_torture_ops *torture_ops[] = -		{ &rcu_ops, &rcu_sync_ops, &rcu_bh_ops, &rcu_bh_sync_ops, -		  &sched_expedited_ops, -		  &srcu_ops, &sched_ops, &sched_ops_sync, }; +		{ &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops, +		  &rcu_bh_ops, &rcu_bh_sync_ops, +		  &srcu_ops, &srcu_expedited_ops, +		  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };  	mutex_lock(&fullstop_mutex); @@ -1110,8 +1145,12 @@ rcu_torture_init(void)  			break;  	}  	if (i == ARRAY_SIZE(torture_ops)) { -		printk(KERN_ALERT "rcutorture: invalid torture type: \"%s\"\n", +		printk(KERN_ALERT "rcu-torture: invalid torture type: \"%s\"\n",  		       torture_type); +		printk(KERN_ALERT "rcu-torture types:"); +		for (i = 0; i < ARRAY_SIZE(torture_ops); i++) +			printk(KERN_ALERT " %s", torture_ops[i]->name); +		printk(KERN_ALERT "\n");  		mutex_unlock(&fullstop_mutex);  		return -EINVAL;  	} diff --git a/kernel/rcutree.c b/kernel/rcutree.c index f3077c0ab18..53ae9598f79 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -46,18 +46,22 @@  #include <linux/cpu.h>  #include <linux/mutex.h>  #include <linux/time.h> +#include <linux/kernel_stat.h>  #include "rcutree.h"  /* Data structures. */ +static struct lock_class_key rcu_node_class[NUM_RCU_LVLS]; +  #define RCU_STATE_INITIALIZER(name) { \  	.level = { &name.node[0] }, \  	.levelcnt = { \  		NUM_RCU_LVL_0,  /* root of hierarchy. */ \  		NUM_RCU_LVL_1, \  		NUM_RCU_LVL_2, \ -		NUM_RCU_LVL_3, /* == MAX_RCU_LVLS */ \ +		NUM_RCU_LVL_3, \ +		NUM_RCU_LVL_4, /* == MAX_RCU_LVLS */ \  	}, \  	.signaled = RCU_GP_IDLE, \  	.gpnum = -300, \ @@ -77,6 +81,8 @@ DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);  struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh_state);  DEFINE_PER_CPU(struct rcu_data, rcu_bh_data); +static int rcu_scheduler_active __read_mostly; +  /*   * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s @@ -98,7 +104,7 @@ void rcu_sched_qs(int cpu)  	struct rcu_data *rdp;  	rdp = &per_cpu(rcu_sched_data, cpu); -	rdp->passed_quiesc_completed = rdp->completed; +	rdp->passed_quiesc_completed = rdp->gpnum - 1;  	barrier();  	rdp->passed_quiesc = 1;  	rcu_preempt_note_context_switch(cpu); @@ -109,7 +115,7 @@ void rcu_bh_qs(int cpu)  	struct rcu_data *rdp;  	rdp = &per_cpu(rcu_bh_data, cpu); -	rdp->passed_quiesc_completed = rdp->completed; +	rdp->passed_quiesc_completed = rdp->gpnum - 1;  	barrier();  	rdp->passed_quiesc = 1;  } @@ -335,28 +341,9 @@ void rcu_irq_exit(void)  		set_need_resched();  } -/* - * Record the specified "completed" value, which is later used to validate - * dynticks counter manipulations.  Specify "rsp->completed - 1" to - * unconditionally invalidate any future dynticks manipulations (which is - * useful at the beginning of a grace period). - */ -static void dyntick_record_completed(struct rcu_state *rsp, long comp) -{ -	rsp->dynticks_completed = comp; -} -  #ifdef CONFIG_SMP  /* - * Recall the previously recorded value of the completion for dynticks. - */ -static long dyntick_recall_completed(struct rcu_state *rsp) -{ -	return rsp->dynticks_completed; -} - -/*   * Snapshot the specified CPU's dynticks counter so that we can later   * credit them with an implicit quiescent state.  Return 1 if this CPU   * is in dynticks idle mode, which is an extended quiescent state. @@ -419,24 +406,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp)  #else /* #ifdef CONFIG_NO_HZ */ -static void dyntick_record_completed(struct rcu_state *rsp, long comp) -{ -} -  #ifdef CONFIG_SMP -/* - * If there are no dynticks, then the only way that a CPU can passively - * be in a quiescent state is to be offline.  Unlike dynticks idle, which - * is a point in time during the prior (already finished) grace period, - * an offline CPU is always in a quiescent state, and thus can be - * unconditionally applied.  So just return the current value of completed. - */ -static long dyntick_recall_completed(struct rcu_state *rsp) -{ -	return rsp->completed; -} -  static int dyntick_save_progress_counter(struct rcu_data *rdp)  {  	return 0; @@ -553,13 +524,33 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)  /*   * Update CPU-local rcu_data state to record the newly noticed grace period.   * This is used both when we started the grace period and when we notice - * that someone else started the grace period. + * that someone else started the grace period.  The caller must hold the + * ->lock of the leaf rcu_node structure corresponding to the current CPU, + *  and must have irqs disabled.   */ +static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp) +{ +	if (rdp->gpnum != rnp->gpnum) { +		rdp->qs_pending = 1; +		rdp->passed_quiesc = 0; +		rdp->gpnum = rnp->gpnum; +	} +} +  static void note_new_gpnum(struct rcu_state *rsp, struct rcu_data *rdp)  { -	rdp->qs_pending = 1; -	rdp->passed_quiesc = 0; -	rdp->gpnum = rsp->gpnum; +	unsigned long flags; +	struct rcu_node *rnp; + +	local_irq_save(flags); +	rnp = rdp->mynode; +	if (rdp->gpnum == ACCESS_ONCE(rnp->gpnum) || /* outside lock. */ +	    !spin_trylock(&rnp->lock)) { /* irqs already off, retry later. */ +		local_irq_restore(flags); +		return; +	} +	__note_new_gpnum(rsp, rnp, rdp); +	spin_unlock_irqrestore(&rnp->lock, flags);  }  /* @@ -583,6 +574,79 @@ check_for_new_grace_period(struct rcu_state *rsp, struct rcu_data *rdp)  }  /* + * Advance this CPU's callbacks, but only if the current grace period + * has ended.  This may be called only from the CPU to whom the rdp + * belongs.  In addition, the corresponding leaf rcu_node structure's + * ->lock must be held by the caller, with irqs disabled. + */ +static void +__rcu_process_gp_end(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp) +{ +	/* Did another grace period end? */ +	if (rdp->completed != rnp->completed) { + +		/* Advance callbacks.  No harm if list empty. */ +		rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL]; +		rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL]; +		rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + +		/* Remember that we saw this grace-period completion. */ +		rdp->completed = rnp->completed; +	} +} + +/* + * Advance this CPU's callbacks, but only if the current grace period + * has ended.  This may be called only from the CPU to whom the rdp + * belongs. + */ +static void +rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp) +{ +	unsigned long flags; +	struct rcu_node *rnp; + +	local_irq_save(flags); +	rnp = rdp->mynode; +	if (rdp->completed == ACCESS_ONCE(rnp->completed) || /* outside lock. */ +	    !spin_trylock(&rnp->lock)) { /* irqs already off, retry later. */ +		local_irq_restore(flags); +		return; +	} +	__rcu_process_gp_end(rsp, rnp, rdp); +	spin_unlock_irqrestore(&rnp->lock, flags); +} + +/* + * Do per-CPU grace-period initialization for running CPU.  The caller + * must hold the lock of the leaf rcu_node structure corresponding to + * this CPU. + */ +static void +rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_data *rdp) +{ +	/* Prior grace period ended, so advance callbacks for current CPU. */ +	__rcu_process_gp_end(rsp, rnp, rdp); + +	/* +	 * Because this CPU just now started the new grace period, we know +	 * that all of its callbacks will be covered by this upcoming grace +	 * period, even the ones that were registered arbitrarily recently. +	 * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL. +	 * +	 * Other CPUs cannot be sure exactly when the grace period started. +	 * Therefore, their recently registered callbacks must pass through +	 * an additional RCU_NEXT_READY stage, so that they will be handled +	 * by the next RCU grace period. +	 */ +	rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; +	rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; + +	/* Set state so that this CPU will detect the next quiescent state. */ +	__note_new_gpnum(rsp, rnp, rdp); +} + +/*   * Start a new RCU grace period if warranted, re-initializing the hierarchy   * in preparation for detecting the next grace period.  The caller must hold   * the root node's ->lock, which is released before return.  Hard irqs must @@ -596,7 +660,23 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)  	struct rcu_node *rnp = rcu_get_root(rsp);  	if (!cpu_needs_another_gp(rsp, rdp)) { -		spin_unlock_irqrestore(&rnp->lock, flags); +		if (rnp->completed == rsp->completed) { +			spin_unlock_irqrestore(&rnp->lock, flags); +			return; +		} +		spin_unlock(&rnp->lock);	 /* irqs remain disabled. */ + +		/* +		 * Propagate new ->completed value to rcu_node structures +		 * so that other CPUs don't have to wait until the start +		 * of the next grace period to process their callbacks. +		 */ +		rcu_for_each_node_breadth_first(rsp, rnp) { +			spin_lock(&rnp->lock);	 /* irqs already disabled. */ +			rnp->completed = rsp->completed; +			spin_unlock(&rnp->lock); /* irqs remain disabled. */ +		} +		local_irq_restore(flags);  		return;  	} @@ -606,29 +686,15 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)  	rsp->signaled = RCU_GP_INIT; /* Hold off force_quiescent_state. */  	rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;  	record_gp_stall_check_time(rsp); -	dyntick_record_completed(rsp, rsp->completed - 1); -	note_new_gpnum(rsp, rdp); - -	/* -	 * Because this CPU just now started the new grace period, we know -	 * that all of its callbacks will be covered by this upcoming grace -	 * period, even the ones that were registered arbitrarily recently. -	 * Therefore, advance all outstanding callbacks to RCU_WAIT_TAIL. -	 * -	 * Other CPUs cannot be sure exactly when the grace period started. -	 * Therefore, their recently registered callbacks must pass through -	 * an additional RCU_NEXT_READY stage, so that they will be handled -	 * by the next RCU grace period. -	 */ -	rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; -	rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_TAIL];  	/* Special-case the common single-level case. */  	if (NUM_RCU_NODES == 1) {  		rcu_preempt_check_blocked_tasks(rnp);  		rnp->qsmask = rnp->qsmaskinit;  		rnp->gpnum = rsp->gpnum; +		rnp->completed = rsp->completed;  		rsp->signaled = RCU_SIGNAL_INIT; /* force_quiescent_state OK. */ +		rcu_start_gp_per_cpu(rsp, rnp, rdp);  		spin_unlock_irqrestore(&rnp->lock, flags);  		return;  	} @@ -661,6 +727,9 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)  		rcu_preempt_check_blocked_tasks(rnp);  		rnp->qsmask = rnp->qsmaskinit;  		rnp->gpnum = rsp->gpnum; +		rnp->completed = rsp->completed; +		if (rnp == rdp->mynode) +			rcu_start_gp_per_cpu(rsp, rnp, rdp);  		spin_unlock(&rnp->lock);	/* irqs remain disabled. */  	} @@ -672,58 +741,32 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags)  }  /* - * Advance this CPU's callbacks, but only if the current grace period - * has ended.  This may be called only from the CPU to whom the rdp - * belongs. + * Report a full set of quiescent states to the specified rcu_state + * data structure.  This involves cleaning up after the prior grace + * period and letting rcu_start_gp() start up the next grace period + * if one is needed.  Note that the caller must hold rnp->lock, as + * required by rcu_start_gp(), which will release it.   */ -static void -rcu_process_gp_end(struct rcu_state *rsp, struct rcu_data *rdp) -{ -	long completed_snap; -	unsigned long flags; - -	local_irq_save(flags); -	completed_snap = ACCESS_ONCE(rsp->completed);  /* outside of lock. */ - -	/* Did another grace period end? */ -	if (rdp->completed != completed_snap) { - -		/* Advance callbacks.  No harm if list empty. */ -		rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[RCU_WAIT_TAIL]; -		rdp->nxttail[RCU_WAIT_TAIL] = rdp->nxttail[RCU_NEXT_READY_TAIL]; -		rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; - -		/* Remember that we saw this grace-period completion. */ -		rdp->completed = completed_snap; -	} -	local_irq_restore(flags); -} - -/* - * Clean up after the prior grace period and let rcu_start_gp() start up - * the next grace period if one is needed.  Note that the caller must - * hold rnp->lock, as required by rcu_start_gp(), which will release it. - */ -static void cpu_quiet_msk_finish(struct rcu_state *rsp, unsigned long flags) +static void rcu_report_qs_rsp(struct rcu_state *rsp, unsigned long flags)  	__releases(rcu_get_root(rsp)->lock)  {  	WARN_ON_ONCE(!rcu_gp_in_progress(rsp));  	rsp->completed = rsp->gpnum;  	rsp->signaled = RCU_GP_IDLE; -	rcu_process_gp_end(rsp, rsp->rda[smp_processor_id()]);  	rcu_start_gp(rsp, flags);  /* releases root node's rnp->lock. */  }  /* - * Similar to cpu_quiet(), for which it is a helper function.  Allows - * a group of CPUs to be quieted at one go, though all the CPUs in the - * group must be represented by the same leaf rcu_node structure. - * That structure's lock must be held upon entry, and it is released - * before return. + * Similar to rcu_report_qs_rdp(), for which it is a helper function. + * Allows quiescent states for a group of CPUs to be reported at one go + * to the specified rcu_node structure, though all the CPUs in the group + * must be represented by the same rcu_node structure (which need not be + * a leaf rcu_node structure, though it often will be).  That structure's + * lock must be held upon entry, and it is released before return.   */  static void -cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, struct rcu_node *rnp, -	      unsigned long flags) +rcu_report_qs_rnp(unsigned long mask, struct rcu_state *rsp, +		  struct rcu_node *rnp, unsigned long flags)  	__releases(rnp->lock)  {  	struct rcu_node *rnp_c; @@ -759,21 +802,23 @@ cpu_quiet_msk(unsigned long mask, struct rcu_state *rsp, struct rcu_node *rnp,  	/*  	 * Get here if we are the last CPU to pass through a quiescent -	 * state for this grace period.  Invoke cpu_quiet_msk_finish() +	 * state for this grace period.  Invoke rcu_report_qs_rsp()  	 * to clean up and start the next grace period if one is needed.  	 */ -	cpu_quiet_msk_finish(rsp, flags); /* releases rnp->lock. */ +	rcu_report_qs_rsp(rsp, flags); /* releases rnp->lock. */  }  /* - * Record a quiescent state for the specified CPU, which must either be - * the current CPU.  The lastcomp argument is used to make sure we are - * still in the grace period of interest.  We don't want to end the current - * grace period based on quiescent states detected in an earlier grace - * period! + * Record a quiescent state for the specified CPU to that CPU's rcu_data + * structure.  This must be either called from the specified CPU, or + * called when the specified CPU is known to be offline (and when it is + * also known that no other CPU is concurrently trying to help the offline + * CPU).  The lastcomp argument is used to make sure we are still in the + * grace period of interest.  We don't want to end the current grace period + * based on quiescent states detected in an earlier grace period!   */  static void -cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp) +rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp)  {  	unsigned long flags;  	unsigned long mask; @@ -781,15 +826,15 @@ cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp)  	rnp = rdp->mynode;  	spin_lock_irqsave(&rnp->lock, flags); -	if (lastcomp != ACCESS_ONCE(rsp->completed)) { +	if (lastcomp != rnp->completed) {  		/*  		 * Someone beat us to it for this grace period, so leave.  		 * The race with GP start is resolved by the fact that we  		 * hold the leaf rcu_node lock, so that the per-CPU bits  		 * cannot yet be initialized -- so we would simply find our -		 * CPU's bit already cleared in cpu_quiet_msk() if this race -		 * occurred. +		 * CPU's bit already cleared in rcu_report_qs_rnp() if this +		 * race occurred.  		 */  		rdp->passed_quiesc = 0;	/* try again later! */  		spin_unlock_irqrestore(&rnp->lock, flags); @@ -807,7 +852,7 @@ cpu_quiet(int cpu, struct rcu_state *rsp, struct rcu_data *rdp, long lastcomp)  		 */  		rdp->nxttail[RCU_NEXT_READY_TAIL] = rdp->nxttail[RCU_NEXT_TAIL]; -		cpu_quiet_msk(mask, rsp, rnp, flags); /* releases rnp->lock */ +		rcu_report_qs_rnp(mask, rsp, rnp, flags); /* rlses rnp->lock */  	}  } @@ -838,8 +883,11 @@ rcu_check_quiescent_state(struct rcu_state *rsp, struct rcu_data *rdp)  	if (!rdp->passed_quiesc)  		return; -	/* Tell RCU we are done (but cpu_quiet() will be the judge of that). */ -	cpu_quiet(rdp->cpu, rsp, rdp, rdp->passed_quiesc_completed); +	/* +	 * Tell RCU we are done (but rcu_report_qs_rdp() will be the +	 * judge of that). +	 */ +	rcu_report_qs_rdp(rdp->cpu, rsp, rdp, rdp->passed_quiesc_completed);  }  #ifdef CONFIG_HOTPLUG_CPU @@ -899,8 +947,8 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp)  static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)  {  	unsigned long flags; -	long lastcomp;  	unsigned long mask; +	int need_report = 0;  	struct rcu_data *rdp = rsp->rda[cpu];  	struct rcu_node *rnp; @@ -914,30 +962,32 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)  		spin_lock(&rnp->lock);		/* irqs already disabled. */  		rnp->qsmaskinit &= ~mask;  		if (rnp->qsmaskinit != 0) { -			spin_unlock(&rnp->lock); /* irqs remain disabled. */ +			if (rnp != rdp->mynode) +				spin_unlock(&rnp->lock); /* irqs remain disabled. */  			break;  		} - -		/* -		 * If there was a task blocking the current grace period, -		 * and if all CPUs have checked in, we need to propagate -		 * the quiescent state up the rcu_node hierarchy.  But that -		 * is inconvenient at the moment due to deadlock issues if -		 * this should end the current grace period.  So set the -		 * offlined CPU's bit in ->qsmask in order to force the -		 * next force_quiescent_state() invocation to clean up this -		 * mess in a deadlock-free manner. -		 */ -		if (rcu_preempt_offline_tasks(rsp, rnp, rdp) && !rnp->qsmask) -			rnp->qsmask |= mask; - +		if (rnp == rdp->mynode) +			need_report = rcu_preempt_offline_tasks(rsp, rnp, rdp); +		else +			spin_unlock(&rnp->lock); /* irqs remain disabled. */  		mask = rnp->grpmask; -		spin_unlock(&rnp->lock);	/* irqs remain disabled. */  		rnp = rnp->parent;  	} while (rnp != NULL); -	lastcomp = rsp->completed; -	spin_unlock_irqrestore(&rsp->onofflock, flags); +	/* +	 * We still hold the leaf rcu_node structure lock here, and +	 * irqs are still disabled.  The reason for this subterfuge is +	 * because invoking rcu_report_unblock_qs_rnp() with ->onofflock +	 * held leads to deadlock. +	 */ +	spin_unlock(&rsp->onofflock); /* irqs remain disabled. */ +	rnp = rdp->mynode; +	if (need_report & RCU_OFL_TASKS_NORM_GP) +		rcu_report_unblock_qs_rnp(rnp, flags); +	else +		spin_unlock_irqrestore(&rnp->lock, flags); +	if (need_report & RCU_OFL_TASKS_EXP_GP) +		rcu_report_exp_rnp(rsp, rnp);  	rcu_adopt_orphan_cbs(rsp);  } @@ -1109,7 +1159,7 @@ static int rcu_process_dyntick(struct rcu_state *rsp, long lastcomp,  	rcu_for_each_leaf_node(rsp, rnp) {  		mask = 0;  		spin_lock_irqsave(&rnp->lock, flags); -		if (rsp->completed != lastcomp) { +		if (rnp->completed != lastcomp) {  			spin_unlock_irqrestore(&rnp->lock, flags);  			return 1;  		} @@ -1123,10 +1173,10 @@ static int rcu_process_dyntick(struct rcu_state *rsp, long lastcomp,  			if ((rnp->qsmask & bit) != 0 && f(rsp->rda[cpu]))  				mask |= bit;  		} -		if (mask != 0 && rsp->completed == lastcomp) { +		if (mask != 0 && rnp->completed == lastcomp) { -			/* cpu_quiet_msk() releases rnp->lock. */ -			cpu_quiet_msk(mask, rsp, rnp, flags); +			/* rcu_report_qs_rnp() releases rnp->lock. */ +			rcu_report_qs_rnp(mask, rsp, rnp, flags);  			continue;  		}  		spin_unlock_irqrestore(&rnp->lock, flags); @@ -1144,6 +1194,7 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)  	long lastcomp;  	struct rcu_node *rnp = rcu_get_root(rsp);  	u8 signaled; +	u8 forcenow;  	if (!rcu_gp_in_progress(rsp))  		return;  /* No grace period in progress, nothing to force. */ @@ -1156,10 +1207,10 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)  		goto unlock_ret; /* no emergency and done recently. */  	rsp->n_force_qs++;  	spin_lock(&rnp->lock); -	lastcomp = rsp->completed; +	lastcomp = rsp->gpnum - 1;  	signaled = rsp->signaled;  	rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; -	if (lastcomp == rsp->gpnum) { +	if(!rcu_gp_in_progress(rsp)) {  		rsp->n_force_qs_ngp++;  		spin_unlock(&rnp->lock);  		goto unlock_ret;  /* no GP in progress, time updated. */ @@ -1180,21 +1231,29 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)  		if (rcu_process_dyntick(rsp, lastcomp,  					dyntick_save_progress_counter))  			goto unlock_ret; +		/* fall into next case. */ + +	case RCU_SAVE_COMPLETED:  		/* Update state, record completion counter. */ +		forcenow = 0;  		spin_lock(&rnp->lock); -		if (lastcomp == rsp->completed && -		    rsp->signaled == RCU_SAVE_DYNTICK) { +		if (lastcomp + 1 == rsp->gpnum && +		    lastcomp == rsp->completed && +		    rsp->signaled == signaled) {  			rsp->signaled = RCU_FORCE_QS; -			dyntick_record_completed(rsp, lastcomp); +			rsp->completed_fqs = lastcomp; +			forcenow = signaled == RCU_SAVE_COMPLETED;  		}  		spin_unlock(&rnp->lock); -		break; +		if (!forcenow) +			break; +		/* fall into next case. */  	case RCU_FORCE_QS:  		/* Check dyntick-idle state, send IPI to laggarts. */ -		if (rcu_process_dyntick(rsp, dyntick_recall_completed(rsp), +		if (rcu_process_dyntick(rsp, rsp->completed_fqs,  					rcu_implicit_dynticks_qs))  			goto unlock_ret; @@ -1351,6 +1410,68 @@ void call_rcu_bh(struct rcu_head *head, void (*func)(struct rcu_head *rcu))  }  EXPORT_SYMBOL_GPL(call_rcu_bh); +/** + * synchronize_sched - wait until an rcu-sched grace period has elapsed. + * + * Control will return to the caller some time after a full rcu-sched + * grace period has elapsed, in other words after all currently executing + * rcu-sched read-side critical sections have completed.   These read-side + * critical sections are delimited by rcu_read_lock_sched() and + * rcu_read_unlock_sched(), and may be nested.  Note that preempt_disable(), + * local_irq_disable(), and so on may be used in place of + * rcu_read_lock_sched(). + * + * This means that all preempt_disable code sequences, including NMI and + * hardware-interrupt handlers, in progress on entry will have completed + * before this primitive returns.  However, this does not guarantee that + * softirq handlers will have completed, since in some kernels, these + * handlers can run in process context, and can block. + * + * This primitive provides the guarantees made by the (now removed) + * synchronize_kernel() API.  In contrast, synchronize_rcu() only + * guarantees that rcu_read_lock() sections will have completed. + * In "classic RCU", these two guarantees happen to be one and + * the same, but can differ in realtime RCU implementations. + */ +void synchronize_sched(void) +{ +	struct rcu_synchronize rcu; + +	if (rcu_blocking_is_gp()) +		return; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu_sched(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +} +EXPORT_SYMBOL_GPL(synchronize_sched); + +/** + * synchronize_rcu_bh - wait until an rcu_bh grace period has elapsed. + * + * Control will return to the caller some time after a full rcu_bh grace + * period has elapsed, in other words after all currently executing rcu_bh + * read-side critical sections have completed.  RCU read-side critical + * sections are delimited by rcu_read_lock_bh() and rcu_read_unlock_bh(), + * and may be nested. + */ +void synchronize_rcu_bh(void) +{ +	struct rcu_synchronize rcu; + +	if (rcu_blocking_is_gp()) +		return; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu_bh(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +} +EXPORT_SYMBOL_GPL(synchronize_rcu_bh); +  /*   * Check to see if there is any immediate RCU-related work to be done   * by the current CPU, for the specified type of RCU, returning 1 if so. @@ -1360,6 +1481,8 @@ EXPORT_SYMBOL_GPL(call_rcu_bh);   */  static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)  { +	struct rcu_node *rnp = rdp->mynode; +  	rdp->n_rcu_pending++;  	/* Check for CPU stalls, if enabled. */ @@ -1384,13 +1507,13 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)  	}  	/* Has another RCU grace period completed?  */ -	if (ACCESS_ONCE(rsp->completed) != rdp->completed) { /* outside lock */ +	if (ACCESS_ONCE(rnp->completed) != rdp->completed) { /* outside lock */  		rdp->n_rp_gp_completed++;  		return 1;  	}  	/* Has a new RCU grace period started? */ -	if (ACCESS_ONCE(rsp->gpnum) != rdp->gpnum) { /* outside lock */ +	if (ACCESS_ONCE(rnp->gpnum) != rdp->gpnum) { /* outside lock */  		rdp->n_rp_gp_started++;  		return 1;  	} @@ -1433,6 +1556,21 @@ int rcu_needs_cpu(int cpu)  	       rcu_preempt_needs_cpu(cpu);  } +/* + * This function is invoked towards the end of the scheduler's initialization + * process.  Before this is called, the idle task might contain + * RCU read-side critical sections (during which time, this idle + * task is booting the system).  After this function is called, the + * idle tasks are prohibited from containing RCU read-side critical + * sections. + */ +void rcu_scheduler_starting(void) +{ +	WARN_ON(num_online_cpus() != 1); +	WARN_ON(nr_context_switches() > 0); +	rcu_scheduler_active = 1; +} +  static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};  static atomic_t rcu_barrier_cpu_count;  static DEFINE_MUTEX(rcu_barrier_mutex); @@ -1544,21 +1682,16 @@ static void __cpuinit  rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)  {  	unsigned long flags; -	long lastcomp;  	unsigned long mask;  	struct rcu_data *rdp = rsp->rda[cpu];  	struct rcu_node *rnp = rcu_get_root(rsp);  	/* Set up local state, ensuring consistent view of global state. */  	spin_lock_irqsave(&rnp->lock, flags); -	lastcomp = rsp->completed; -	rdp->completed = lastcomp; -	rdp->gpnum = lastcomp;  	rdp->passed_quiesc = 0;  /* We could be racing with new GP, */  	rdp->qs_pending = 1;	 /*  so set up to respond to current GP. */  	rdp->beenonline = 1;	 /* We have now been online. */  	rdp->preemptable = preemptable; -	rdp->passed_quiesc_completed = lastcomp - 1;  	rdp->qlen_last_fqs_check = 0;  	rdp->n_force_qs_snap = rsp->n_force_qs;  	rdp->blimit = blimit; @@ -1580,6 +1713,11 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptable)  		spin_lock(&rnp->lock);	/* irqs already disabled. */  		rnp->qsmaskinit |= mask;  		mask = rnp->grpmask; +		if (rnp == rdp->mynode) { +			rdp->gpnum = rnp->completed; /* if GP in progress... */ +			rdp->completed = rnp->completed; +			rdp->passed_quiesc_completed = rnp->completed - 1; +		}  		spin_unlock(&rnp->lock); /* irqs already disabled. */  		rnp = rnp->parent;  	} while (rnp != NULL && !(rnp->qsmaskinit & mask)); @@ -1597,8 +1735,8 @@ static void __cpuinit rcu_online_cpu(int cpu)  /*   * Handle CPU online/offline notification events.   */ -int __cpuinit rcu_cpu_notify(struct notifier_block *self, -			     unsigned long action, void *hcpu) +static int __cpuinit rcu_cpu_notify(struct notifier_block *self, +				    unsigned long action, void *hcpu)  {  	long cpu = (long)hcpu; @@ -1685,8 +1823,8 @@ static void __init rcu_init_one(struct rcu_state *rsp)  		cpustride *= rsp->levelspread[i];  		rnp = rsp->level[i];  		for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) { -			if (rnp != rcu_get_root(rsp)) -				spin_lock_init(&rnp->lock); +			spin_lock_init(&rnp->lock); +			lockdep_set_class(&rnp->lock, &rcu_node_class[i]);  			rnp->gpnum = 0;  			rnp->qsmask = 0;  			rnp->qsmaskinit = 0; @@ -1707,9 +1845,10 @@ static void __init rcu_init_one(struct rcu_state *rsp)  			rnp->level = i;  			INIT_LIST_HEAD(&rnp->blocked_tasks[0]);  			INIT_LIST_HEAD(&rnp->blocked_tasks[1]); +			INIT_LIST_HEAD(&rnp->blocked_tasks[2]); +			INIT_LIST_HEAD(&rnp->blocked_tasks[3]);  		}  	} -	spin_lock_init(&rcu_get_root(rsp)->lock);  }  /* @@ -1735,16 +1874,30 @@ do { \  	} \  } while (0) -void __init __rcu_init(void) +void __init rcu_init(void)  { +	int i; +  	rcu_bootup_announce();  #ifdef CONFIG_RCU_CPU_STALL_DETECTOR  	printk(KERN_INFO "RCU-based detection of stalled CPUs is enabled.\n");  #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ +#if NUM_RCU_LVL_4 != 0 +	printk(KERN_INFO "Experimental four-level hierarchy is enabled.\n"); +#endif /* #if NUM_RCU_LVL_4 != 0 */  	RCU_INIT_FLAVOR(&rcu_sched_state, rcu_sched_data);  	RCU_INIT_FLAVOR(&rcu_bh_state, rcu_bh_data);  	__rcu_init_preempt();  	open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); + +	/* +	 * We don't need protection against CPU-hotplug here because +	 * this is called early in boot, before either interrupts +	 * or the scheduler are operational. +	 */ +	cpu_notifier(rcu_cpu_notify, 0); +	for_each_online_cpu(i) +		rcu_cpu_notify(NULL, CPU_UP_PREPARE, (void *)(long)i);  }  #include "rcutree_plugin.h" diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 1899023b096..d2a0046f63b 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -34,10 +34,11 @@   * In practice, this has not been tested, so there is probably some   * bug somewhere.   */ -#define MAX_RCU_LVLS 3 +#define MAX_RCU_LVLS 4  #define RCU_FANOUT	      (CONFIG_RCU_FANOUT)  #define RCU_FANOUT_SQ	      (RCU_FANOUT * RCU_FANOUT)  #define RCU_FANOUT_CUBE	      (RCU_FANOUT_SQ * RCU_FANOUT) +#define RCU_FANOUT_FOURTH     (RCU_FANOUT_CUBE * RCU_FANOUT)  #if NR_CPUS <= RCU_FANOUT  #  define NUM_RCU_LVLS	      1 @@ -45,23 +46,33 @@  #  define NUM_RCU_LVL_1	      (NR_CPUS)  #  define NUM_RCU_LVL_2	      0  #  define NUM_RCU_LVL_3	      0 +#  define NUM_RCU_LVL_4	      0  #elif NR_CPUS <= RCU_FANOUT_SQ  #  define NUM_RCU_LVLS	      2  #  define NUM_RCU_LVL_0	      1  #  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)  #  define NUM_RCU_LVL_2	      (NR_CPUS)  #  define NUM_RCU_LVL_3	      0 +#  define NUM_RCU_LVL_4	      0  #elif NR_CPUS <= RCU_FANOUT_CUBE  #  define NUM_RCU_LVLS	      3  #  define NUM_RCU_LVL_0	      1  #  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ)  #  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT)  #  define NUM_RCU_LVL_3	      NR_CPUS +#  define NUM_RCU_LVL_4	      0 +#elif NR_CPUS <= RCU_FANOUT_FOURTH +#  define NUM_RCU_LVLS	      4 +#  define NUM_RCU_LVL_0	      1 +#  define NUM_RCU_LVL_1	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_CUBE) +#  define NUM_RCU_LVL_2	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_SQ) +#  define NUM_RCU_LVL_3	      DIV_ROUND_UP(NR_CPUS, RCU_FANOUT) +#  define NUM_RCU_LVL_4	      NR_CPUS  #else  # error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"  #endif /* #if (NR_CPUS) <= RCU_FANOUT */ -#define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3) +#define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3 + NUM_RCU_LVL_4)  #define NUM_RCU_NODES (RCU_SUM - NR_CPUS)  /* @@ -84,14 +95,21 @@ struct rcu_node {  	long	gpnum;		/* Current grace period for this node. */  				/*  This will either be equal to or one */  				/*  behind the root rcu_node's gpnum. */ +	long	completed;	/* Last grace period completed for this node. */ +				/*  This will either be equal to or one */ +				/*  behind the root rcu_node's gpnum. */  	unsigned long qsmask;	/* CPUs or groups that need to switch in */  				/*  order for current grace period to proceed.*/  				/*  In leaf rcu_node, each bit corresponds to */  				/*  an rcu_data structure, otherwise, each */  				/*  bit corresponds to a child rcu_node */  				/*  structure. */ +	unsigned long expmask;	/* Groups that have ->blocked_tasks[] */ +				/*  elements that need to drain to allow the */ +				/*  current expedited grace period to */ +				/*  complete (only for TREE_PREEMPT_RCU). */  	unsigned long qsmaskinit; -				/* Per-GP initialization for qsmask. */ +				/* Per-GP initial value for qsmask & expmask. */  	unsigned long grpmask;	/* Mask to apply to parent qsmask. */  				/*  Only one bit will be set in this mask. */  	int	grplo;		/* lowest-numbered CPU or group here. */ @@ -99,7 +117,7 @@ struct rcu_node {  	u8	grpnum;		/* CPU/group number for next level up. */  	u8	level;		/* root is at level 0. */  	struct rcu_node *parent; -	struct list_head blocked_tasks[2]; +	struct list_head blocked_tasks[4];  				/* Tasks blocked in RCU read-side critsect. */  				/*  Grace period number (->gpnum) x blocked */  				/*  by tasks on the (x & 0x1) element of the */ @@ -114,6 +132,21 @@ struct rcu_node {  	for ((rnp) = &(rsp)->node[0]; \  	     (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++) +/* + * Do a breadth-first scan of the non-leaf rcu_node structures for the + * specified rcu_state structure.  Note that if there is a singleton + * rcu_node tree with but one rcu_node structure, this loop is a no-op. + */ +#define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \ +	for ((rnp) = &(rsp)->node[0]; \ +	     (rnp) < (rsp)->level[NUM_RCU_LVLS - 1]; (rnp)++) + +/* + * Scan the leaves of the rcu_node hierarchy for the specified rcu_state + * structure.  Note that if there is a singleton rcu_node tree with but + * one rcu_node structure, this loop -will- visit the rcu_node structure. + * It is still a leaf node, even if it is also the root node. + */  #define rcu_for_each_leaf_node(rsp, rnp) \  	for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \  	     (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++) @@ -204,11 +237,12 @@ struct rcu_data {  #define RCU_GP_IDLE		0	/* No grace period in progress. */  #define RCU_GP_INIT		1	/* Grace period being initialized. */  #define RCU_SAVE_DYNTICK	2	/* Need to scan dyntick state. */ -#define RCU_FORCE_QS		3	/* Need to force quiescent state. */ +#define RCU_SAVE_COMPLETED	3	/* Need to save rsp->completed. */ +#define RCU_FORCE_QS		4	/* Need to force quiescent state. */  #ifdef CONFIG_NO_HZ  #define RCU_SIGNAL_INIT		RCU_SAVE_DYNTICK  #else /* #ifdef CONFIG_NO_HZ */ -#define RCU_SIGNAL_INIT		RCU_FORCE_QS +#define RCU_SIGNAL_INIT		RCU_SAVE_COMPLETED  #endif /* #else #ifdef CONFIG_NO_HZ */  #define RCU_JIFFIES_TILL_FORCE_QS	 3	/* for rsp->jiffies_force_qs */ @@ -246,7 +280,7 @@ struct rcu_state {  	long	gpnum;				/* Current gp number. */  	long	completed;			/* # of last completed gp. */ -	/* End  of fields guarded by root rcu_node's lock. */ +	/* End of fields guarded by root rcu_node's lock. */  	spinlock_t onofflock;			/* exclude on/offline and */  						/*  starting new GP.  Also */ @@ -260,6 +294,8 @@ struct rcu_state {  	long orphan_qlen;			/* Number of orphaned cbs. */  	spinlock_t fqslock;			/* Only one task forcing */  						/*  quiescent states. */ +	long	completed_fqs;			/* Value of completed @ snap. */ +						/*  Protected by fqslock. */  	unsigned long jiffies_force_qs;		/* Time at which to invoke */  						/*  force_quiescent_state(). */  	unsigned long n_force_qs;		/* Number of calls to */ @@ -274,11 +310,15 @@ struct rcu_state {  	unsigned long jiffies_stall;		/* Time at which to check */  						/*  for CPU stalls. */  #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ -#ifdef CONFIG_NO_HZ -	long dynticks_completed;		/* Value of completed @ snap. */ -#endif /* #ifdef CONFIG_NO_HZ */  }; +/* Return values for rcu_preempt_offline_tasks(). */ + +#define RCU_OFL_TASKS_NORM_GP	0x1		/* Tasks blocking normal */ +						/*  GP were moved to root. */ +#define RCU_OFL_TASKS_EXP_GP	0x2		/* Tasks blocking expedited */ +						/*  GP were moved to root. */ +  #ifdef RCU_TREE_NONCORE  /* @@ -298,10 +338,14 @@ DECLARE_PER_CPU(struct rcu_data, rcu_preempt_data);  #else /* #ifdef RCU_TREE_NONCORE */  /* Forward declarations for rcutree_plugin.h */ -static inline void rcu_bootup_announce(void); +static void rcu_bootup_announce(void);  long rcu_batches_completed(void);  static void rcu_preempt_note_context_switch(int cpu);  static int rcu_preempted_readers(struct rcu_node *rnp); +#ifdef CONFIG_HOTPLUG_CPU +static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, +				      unsigned long flags); +#endif /* #ifdef CONFIG_HOTPLUG_CPU */  #ifdef CONFIG_RCU_CPU_STALL_DETECTOR  static void rcu_print_task_stall(struct rcu_node *rnp);  #endif /* #ifdef CONFIG_RCU_CPU_STALL_DETECTOR */ @@ -315,6 +359,9 @@ static void rcu_preempt_offline_cpu(int cpu);  static void rcu_preempt_check_callbacks(int cpu);  static void rcu_preempt_process_callbacks(void);  void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); +#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) +static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp); +#endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) */  static int rcu_preempt_pending(int cpu);  static int rcu_preempt_needs_cpu(int cpu);  static void __cpuinit rcu_preempt_init_percpu_data(int cpu); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index ef2a58c2b9d..37fbccdf41d 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -24,16 +24,19 @@   *	   Paul E. McKenney <paulmck@linux.vnet.ibm.com>   */ +#include <linux/delay.h>  #ifdef CONFIG_TREE_PREEMPT_RCU  struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt_state);  DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data); +static int rcu_preempted_readers_exp(struct rcu_node *rnp); +  /*   * Tell them what RCU they are running.   */ -static inline void rcu_bootup_announce(void) +static void __init rcu_bootup_announce(void)  {  	printk(KERN_INFO  	       "Experimental preemptable hierarchical RCU implementation.\n"); @@ -67,7 +70,7 @@ EXPORT_SYMBOL_GPL(rcu_batches_completed);  static void rcu_preempt_qs(int cpu)  {  	struct rcu_data *rdp = &per_cpu(rcu_preempt_data, cpu); -	rdp->passed_quiesc_completed = rdp->completed; +	rdp->passed_quiesc_completed = rdp->gpnum - 1;  	barrier();  	rdp->passed_quiesc = 1;  } @@ -157,14 +160,58 @@ EXPORT_SYMBOL_GPL(__rcu_read_lock);   */  static int rcu_preempted_readers(struct rcu_node *rnp)  { -	return !list_empty(&rnp->blocked_tasks[rnp->gpnum & 0x1]); +	int phase = rnp->gpnum & 0x1; + +	return !list_empty(&rnp->blocked_tasks[phase]) || +	       !list_empty(&rnp->blocked_tasks[phase + 2]); +} + +/* + * Record a quiescent state for all tasks that were previously queued + * on the specified rcu_node structure and that were blocking the current + * RCU grace period.  The caller must hold the specified rnp->lock with + * irqs disabled, and this lock is released upon return, but irqs remain + * disabled. + */ +static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) +	__releases(rnp->lock) +{ +	unsigned long mask; +	struct rcu_node *rnp_p; + +	if (rnp->qsmask != 0 || rcu_preempted_readers(rnp)) { +		spin_unlock_irqrestore(&rnp->lock, flags); +		return;  /* Still need more quiescent states! */ +	} + +	rnp_p = rnp->parent; +	if (rnp_p == NULL) { +		/* +		 * Either there is only one rcu_node in the tree, +		 * or tasks were kicked up to root rcu_node due to +		 * CPUs going offline. +		 */ +		rcu_report_qs_rsp(&rcu_preempt_state, flags); +		return; +	} + +	/* Report up the rest of the hierarchy. */ +	mask = rnp->grpmask; +	spin_unlock(&rnp->lock);	/* irqs remain disabled. */ +	spin_lock(&rnp_p->lock);	/* irqs already disabled. */ +	rcu_report_qs_rnp(mask, &rcu_preempt_state, rnp_p, flags);  } +/* + * Handle special cases during rcu_read_unlock(), such as needing to + * notify RCU core processing or task having blocked during the RCU + * read-side critical section. + */  static void rcu_read_unlock_special(struct task_struct *t)  {  	int empty; +	int empty_exp;  	unsigned long flags; -	unsigned long mask;  	struct rcu_node *rnp;  	int special; @@ -207,36 +254,30 @@ static void rcu_read_unlock_special(struct task_struct *t)  			spin_unlock(&rnp->lock);  /* irqs remain disabled. */  		}  		empty = !rcu_preempted_readers(rnp); +		empty_exp = !rcu_preempted_readers_exp(rnp); +		smp_mb(); /* ensure expedited fastpath sees end of RCU c-s. */  		list_del_init(&t->rcu_node_entry);  		t->rcu_blocked_node = NULL;  		/*  		 * If this was the last task on the current list, and if  		 * we aren't waiting on any CPUs, report the quiescent state. -		 * Note that both cpu_quiet_msk_finish() and cpu_quiet_msk() -		 * drop rnp->lock and restore irq. +		 * Note that rcu_report_unblock_qs_rnp() releases rnp->lock.  		 */ -		if (!empty && rnp->qsmask == 0 && -		    !rcu_preempted_readers(rnp)) { -			struct rcu_node *rnp_p; - -			if (rnp->parent == NULL) { -				/* Only one rcu_node in the tree. */ -				cpu_quiet_msk_finish(&rcu_preempt_state, flags); -				return; -			} -			/* Report up the rest of the hierarchy. */ -			mask = rnp->grpmask; +		if (empty)  			spin_unlock_irqrestore(&rnp->lock, flags); -			rnp_p = rnp->parent; -			spin_lock_irqsave(&rnp_p->lock, flags); -			WARN_ON_ONCE(rnp->qsmask); -			cpu_quiet_msk(mask, &rcu_preempt_state, rnp_p, flags); -			return; -		} -		spin_unlock(&rnp->lock); +		else +			rcu_report_unblock_qs_rnp(rnp, flags); + +		/* +		 * If this was the last task on the expedited lists, +		 * then we need to report up the rcu_node hierarchy. +		 */ +		if (!empty_exp && !rcu_preempted_readers_exp(rnp)) +			rcu_report_exp_rnp(&rcu_preempt_state, rnp); +	} else { +		local_irq_restore(flags);  	} -	local_irq_restore(flags);  }  /* @@ -303,6 +344,8 @@ static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp)   * rcu_node.  The reason for not just moving them to the immediate   * parent is to remove the need for rcu_read_unlock_special() to   * make more than two attempts to acquire the target rcu_node's lock. + * Returns true if there were tasks blocking the current RCU grace + * period.   *   * Returns 1 if there was previously a task blocking the current grace   * period on the specified rcu_node structure. @@ -316,7 +359,7 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,  	int i;  	struct list_head *lp;  	struct list_head *lp_root; -	int retval = rcu_preempted_readers(rnp); +	int retval = 0;  	struct rcu_node *rnp_root = rcu_get_root(rsp);  	struct task_struct *tp; @@ -326,7 +369,9 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,  	}  	WARN_ON_ONCE(rnp != rdp->mynode &&  		     (!list_empty(&rnp->blocked_tasks[0]) || -		      !list_empty(&rnp->blocked_tasks[1]))); +		      !list_empty(&rnp->blocked_tasks[1]) || +		      !list_empty(&rnp->blocked_tasks[2]) || +		      !list_empty(&rnp->blocked_tasks[3])));  	/*  	 * Move tasks up to root rcu_node.  Rely on the fact that the @@ -334,7 +379,11 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,  	 * rcu_nodes in terms of gp_num value.  This fact allows us to  	 * move the blocked_tasks[] array directly, element by element.  	 */ -	for (i = 0; i < 2; i++) { +	if (rcu_preempted_readers(rnp)) +		retval |= RCU_OFL_TASKS_NORM_GP; +	if (rcu_preempted_readers_exp(rnp)) +		retval |= RCU_OFL_TASKS_EXP_GP; +	for (i = 0; i < 4; i++) {  		lp = &rnp->blocked_tasks[i];  		lp_root = &rnp_root->blocked_tasks[i];  		while (!list_empty(lp)) { @@ -346,7 +395,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,  			spin_unlock(&rnp_root->lock); /* irqs remain disabled */  		}  	} -  	return retval;  } @@ -398,14 +446,183 @@ void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu))  }  EXPORT_SYMBOL_GPL(call_rcu); +/** + * synchronize_rcu - wait until a grace period has elapsed. + * + * Control will return to the caller some time after a full grace + * period has elapsed, in other words after all currently executing RCU + * read-side critical sections have completed.  RCU read-side critical + * sections are delimited by rcu_read_lock() and rcu_read_unlock(), + * and may be nested. + */ +void synchronize_rcu(void) +{ +	struct rcu_synchronize rcu; + +	if (!rcu_scheduler_active) +		return; + +	init_completion(&rcu.completion); +	/* Will wake me after RCU finished. */ +	call_rcu(&rcu.head, wakeme_after_rcu); +	/* Wait for it. */ +	wait_for_completion(&rcu.completion); +} +EXPORT_SYMBOL_GPL(synchronize_rcu); + +static DECLARE_WAIT_QUEUE_HEAD(sync_rcu_preempt_exp_wq); +static long sync_rcu_preempt_exp_count; +static DEFINE_MUTEX(sync_rcu_preempt_exp_mutex); + +/* + * Return non-zero if there are any tasks in RCU read-side critical + * sections blocking the current preemptible-RCU expedited grace period. + * If there is no preemptible-RCU expedited grace period currently in + * progress, returns zero unconditionally. + */ +static int rcu_preempted_readers_exp(struct rcu_node *rnp) +{ +	return !list_empty(&rnp->blocked_tasks[2]) || +	       !list_empty(&rnp->blocked_tasks[3]); +} + +/* + * return non-zero if there is no RCU expedited grace period in progress + * for the specified rcu_node structure, in other words, if all CPUs and + * tasks covered by the specified rcu_node structure have done their bit + * for the current expedited grace period.  Works only for preemptible + * RCU -- other RCU implementation use other means. + * + * Caller must hold sync_rcu_preempt_exp_mutex. + */ +static int sync_rcu_preempt_exp_done(struct rcu_node *rnp) +{ +	return !rcu_preempted_readers_exp(rnp) && +	       ACCESS_ONCE(rnp->expmask) == 0; +} + +/* + * Report the exit from RCU read-side critical section for the last task + * that queued itself during or before the current expedited preemptible-RCU + * grace period.  This event is reported either to the rcu_node structure on + * which the task was queued or to one of that rcu_node structure's ancestors, + * recursively up the tree.  (Calm down, calm down, we do the recursion + * iteratively!) + * + * Caller must hold sync_rcu_preempt_exp_mutex. + */ +static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp) +{ +	unsigned long flags; +	unsigned long mask; + +	spin_lock_irqsave(&rnp->lock, flags); +	for (;;) { +		if (!sync_rcu_preempt_exp_done(rnp)) +			break; +		if (rnp->parent == NULL) { +			wake_up(&sync_rcu_preempt_exp_wq); +			break; +		} +		mask = rnp->grpmask; +		spin_unlock(&rnp->lock); /* irqs remain disabled */ +		rnp = rnp->parent; +		spin_lock(&rnp->lock); /* irqs already disabled */ +		rnp->expmask &= ~mask; +	} +	spin_unlock_irqrestore(&rnp->lock, flags); +} + +/* + * Snapshot the tasks blocking the newly started preemptible-RCU expedited + * grace period for the specified rcu_node structure.  If there are no such + * tasks, report it up the rcu_node hierarchy. + * + * Caller must hold sync_rcu_preempt_exp_mutex and rsp->onofflock. + */ +static void +sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp) +{ +	int must_wait; + +	spin_lock(&rnp->lock); /* irqs already disabled */ +	list_splice_init(&rnp->blocked_tasks[0], &rnp->blocked_tasks[2]); +	list_splice_init(&rnp->blocked_tasks[1], &rnp->blocked_tasks[3]); +	must_wait = rcu_preempted_readers_exp(rnp); +	spin_unlock(&rnp->lock); /* irqs remain disabled */ +	if (!must_wait) +		rcu_report_exp_rnp(rsp, rnp); +} +  /* - * Wait for an rcu-preempt grace period.  We are supposed to expedite the - * grace period, but this is the crude slow compatability hack, so just - * invoke synchronize_rcu(). + * Wait for an rcu-preempt grace period, but expedite it.  The basic idea + * is to invoke synchronize_sched_expedited() to push all the tasks to + * the ->blocked_tasks[] lists, move all entries from the first set of + * ->blocked_tasks[] lists to the second set, and finally wait for this + * second set to drain.   */  void synchronize_rcu_expedited(void)  { -	synchronize_rcu(); +	unsigned long flags; +	struct rcu_node *rnp; +	struct rcu_state *rsp = &rcu_preempt_state; +	long snap; +	int trycount = 0; + +	smp_mb(); /* Caller's modifications seen first by other CPUs. */ +	snap = ACCESS_ONCE(sync_rcu_preempt_exp_count) + 1; +	smp_mb(); /* Above access cannot bleed into critical section. */ + +	/* +	 * Acquire lock, falling back to synchronize_rcu() if too many +	 * lock-acquisition failures.  Of course, if someone does the +	 * expedited grace period for us, just leave. +	 */ +	while (!mutex_trylock(&sync_rcu_preempt_exp_mutex)) { +		if (trycount++ < 10) +			udelay(trycount * num_online_cpus()); +		else { +			synchronize_rcu(); +			return; +		} +		if ((ACCESS_ONCE(sync_rcu_preempt_exp_count) - snap) > 0) +			goto mb_ret; /* Others did our work for us. */ +	} +	if ((ACCESS_ONCE(sync_rcu_preempt_exp_count) - snap) > 0) +		goto unlock_mb_ret; /* Others did our work for us. */ + +	/* force all RCU readers onto blocked_tasks[]. */ +	synchronize_sched_expedited(); + +	spin_lock_irqsave(&rsp->onofflock, flags); + +	/* Initialize ->expmask for all non-leaf rcu_node structures. */ +	rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) { +		spin_lock(&rnp->lock); /* irqs already disabled. */ +		rnp->expmask = rnp->qsmaskinit; +		spin_unlock(&rnp->lock); /* irqs remain disabled. */ +	} + +	/* Snapshot current state of ->blocked_tasks[] lists. */ +	rcu_for_each_leaf_node(rsp, rnp) +		sync_rcu_preempt_exp_init(rsp, rnp); +	if (NUM_RCU_NODES > 1) +		sync_rcu_preempt_exp_init(rsp, rcu_get_root(rsp)); + +	spin_unlock_irqrestore(&rsp->onofflock, flags); + +	/* Wait for snapshotted ->blocked_tasks[] lists to drain. */ +	rnp = rcu_get_root(rsp); +	wait_event(sync_rcu_preempt_exp_wq, +		   sync_rcu_preempt_exp_done(rnp)); + +	/* Clean up and exit. */ +	smp_mb(); /* ensure expedited GP seen before counter increment. */ +	ACCESS_ONCE(sync_rcu_preempt_exp_count)++; +unlock_mb_ret: +	mutex_unlock(&sync_rcu_preempt_exp_mutex); +mb_ret: +	smp_mb(); /* ensure subsequent action seen after grace period. */  }  EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); @@ -481,7 +698,7 @@ void exit_rcu(void)  /*   * Tell them what RCU they are running.   */ -static inline void rcu_bootup_announce(void) +static void __init rcu_bootup_announce(void)  {  	printk(KERN_INFO "Hierarchical RCU implementation.\n");  } @@ -512,6 +729,16 @@ static int rcu_preempted_readers(struct rcu_node *rnp)  	return 0;  } +#ifdef CONFIG_HOTPLUG_CPU + +/* Because preemptible RCU does not exist, no quieting of tasks. */ +static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp, unsigned long flags) +{ +	spin_unlock_irqrestore(&rnp->lock, flags); +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ +  #ifdef CONFIG_RCU_CPU_STALL_DETECTOR  /* @@ -594,6 +821,20 @@ void synchronize_rcu_expedited(void)  }  EXPORT_SYMBOL_GPL(synchronize_rcu_expedited); +#ifdef CONFIG_HOTPLUG_CPU + +/* + * Because preemptable RCU does not exist, there is never any need to + * report on tasks preempted in RCU read-side critical sections during + * expedited RCU grace periods. + */ +static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp) +{ +	return; +} + +#endif /* #ifdef CONFIG_HOTPLUG_CPU */ +  /*   * Because preemptable RCU does not exist, it never has any work to do.   */ diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c index 4b31c779e62..9d2c88423b3 100644 --- a/kernel/rcutree_trace.c +++ b/kernel/rcutree_trace.c @@ -155,12 +155,15 @@ static const struct file_operations rcudata_csv_fops = {  static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)  { +	long gpnum;  	int level = 0; +	int phase;  	struct rcu_node *rnp; +	gpnum = rsp->gpnum;  	seq_printf(m, "c=%ld g=%ld s=%d jfq=%ld j=%x "  		      "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld\n", -		   rsp->completed, rsp->gpnum, rsp->signaled, +		   rsp->completed, gpnum, rsp->signaled,  		   (long)(rsp->jiffies_force_qs - jiffies),  		   (int)(jiffies & 0xffff),  		   rsp->n_force_qs, rsp->n_force_qs_ngp, @@ -171,8 +174,13 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)  			seq_puts(m, "\n");  			level = rnp->level;  		} -		seq_printf(m, "%lx/%lx %d:%d ^%d    ", +		phase = gpnum & 0x1; +		seq_printf(m, "%lx/%lx %c%c>%c%c %d:%d ^%d    ",  			   rnp->qsmask, rnp->qsmaskinit, +			   "T."[list_empty(&rnp->blocked_tasks[phase])], +			   "E."[list_empty(&rnp->blocked_tasks[phase + 2])], +			   "T."[list_empty(&rnp->blocked_tasks[!phase])], +			   "E."[list_empty(&rnp->blocked_tasks[!phase + 2])],  			   rnp->grplo, rnp->grphi, rnp->grpnum);  	}  	seq_puts(m, "\n"); diff --git a/kernel/sched.c b/kernel/sched.c index 3c11ae0a948..6ae2739b8f1 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -5481,7 +5481,7 @@ need_resched_nonpreemptible:  }  EXPORT_SYMBOL(schedule); -#ifdef CONFIG_SMP +#ifdef CONFIG_MUTEX_SPIN_ON_OWNER  /*   * Look out! "owner" is an entirely speculative pointer   * access and not reliable. @@ -10901,6 +10901,7 @@ void synchronize_sched_expedited(void)  		spin_unlock_irqrestore(&rq->lock, flags);  	}  	rcu_expedited_state = RCU_EXPEDITED_STATE_IDLE; +	synchronize_sched_expedited_count++;  	mutex_unlock(&rcu_sched_expedited_mutex);  	put_online_cpus();  	if (need_full_sync) diff --git a/kernel/signal.c b/kernel/signal.c index 6705320784f..fe08008133d 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -22,6 +22,7 @@  #include <linux/ptrace.h>  #include <linux/signal.h>  #include <linux/signalfd.h> +#include <linux/ratelimit.h>  #include <linux/tracehook.h>  #include <linux/capability.h>  #include <linux/freezer.h> @@ -41,6 +42,8 @@  static struct kmem_cache *sigqueue_cachep; +int print_fatal_signals __read_mostly; +  static void __user *sig_handler(struct task_struct *t, int sig)  {  	return t->sighand->action[sig - 1].sa.sa_handler; @@ -159,7 +162,7 @@ int next_signal(struct sigpending *pending, sigset_t *mask)  {  	unsigned long i, *s, *m, x;  	int sig = 0; -	 +  	s = pending->signal.sig;  	m = mask->sig;  	switch (_NSIG_WORDS) { @@ -184,17 +187,31 @@ int next_signal(struct sigpending *pending, sigset_t *mask)  			sig = ffz(~x) + 1;  		break;  	} -	 +  	return sig;  } +static inline void print_dropped_signal(int sig) +{ +	static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 10); + +	if (!print_fatal_signals) +		return; + +	if (!__ratelimit(&ratelimit_state)) +		return; + +	printk(KERN_INFO "%s/%d: reached RLIMIT_SIGPENDING, dropped signal %d\n", +				current->comm, current->pid, sig); +} +  /*   * allocate a new signal queue record   * - this may be called without locks if and only if t == current, otherwise an   *   appopriate lock must be held to stop the target task from exiting   */ -static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, -					 int override_rlimit) +static struct sigqueue * +__sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimit)  {  	struct sigqueue *q = NULL;  	struct user_struct *user; @@ -207,10 +224,15 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,  	 */  	user = get_uid(__task_cred(t)->user);  	atomic_inc(&user->sigpending); +  	if (override_rlimit ||  	    atomic_read(&user->sigpending) <= -			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) +			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) {  		q = kmem_cache_alloc(sigqueue_cachep, flags); +	} else { +		print_dropped_signal(sig); +	} +  	if (unlikely(q == NULL)) {  		atomic_dec(&user->sigpending);  		free_uid(user); @@ -869,7 +891,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  	else  		override_rlimit = 0; -	q = __sigqueue_alloc(t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE, +	q = __sigqueue_alloc(sig, t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE,  		override_rlimit);  	if (q) {  		list_add_tail(&q->list, &pending->list); @@ -925,8 +947,6 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,  	return __send_signal(sig, info, t, group, from_ancestor_ns);  } -int print_fatal_signals; -  static void print_fatal_signal(struct pt_regs *regs, int signr)  {  	printk("%s/%d: potentially unexpected fatal signal %d.\n", @@ -1293,19 +1313,19 @@ EXPORT_SYMBOL(kill_pid);   * These functions support sending signals using preallocated sigqueue   * structures.  This is needed "because realtime applications cannot   * afford to lose notifications of asynchronous events, like timer - * expirations or I/O completions".  In the case of Posix Timers  + * expirations or I/O completions".  In the case of Posix Timers   * we allocate the sigqueue structure from the timer_create.  If this   * allocation fails we are able to report the failure to the application   * with an EAGAIN error.   */ -   struct sigqueue *sigqueue_alloc(void)  { -	struct sigqueue *q; +	struct sigqueue *q = __sigqueue_alloc(-1, current, GFP_KERNEL, 0); -	if ((q = __sigqueue_alloc(current, GFP_KERNEL, 0))) +	if (q)  		q->flags |= SIGQUEUE_PREALLOC; -	return(q); + +	return q;  }  void sigqueue_free(struct sigqueue *q) diff --git a/kernel/smp.c b/kernel/smp.c index c9d1c7835c2..a8c76069cf5 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -265,9 +265,7 @@ static DEFINE_PER_CPU(struct call_single_data, csd_data);   * @info: An arbitrary pointer to pass to the function.   * @wait: If true, wait until function has completed on other CPUs.   * - * Returns 0 on success, else a negative status code. Note that @wait - * will be implicitly turned on in case of allocation failures, since - * we fall back to on-stack allocation. + * Returns 0 on success, else a negative status code.   */  int smp_call_function_single(int cpu, void (*func) (void *info), void *info,  			     int wait) @@ -321,6 +319,51 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,  }  EXPORT_SYMBOL(smp_call_function_single); +/* + * smp_call_function_any - Run a function on any of the given cpus + * @mask: The mask of cpus it can run on. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @wait: If true, wait until function has completed. + * + * Returns 0 on success, else a negative status code (if no cpus were online). + * Note that @wait will be implicitly turned on in case of allocation failures, + * since we fall back to on-stack allocation. + * + * Selection preference: + *	1) current cpu if in @mask + *	2) any cpu of current node if in @mask + *	3) any other online cpu in @mask + */ +int smp_call_function_any(const struct cpumask *mask, +			  void (*func)(void *info), void *info, int wait) +{ +	unsigned int cpu; +	const struct cpumask *nodemask; +	int ret; + +	/* Try for same CPU (cheapest) */ +	cpu = get_cpu(); +	if (cpumask_test_cpu(cpu, mask)) +		goto call; + +	/* Try for same node. */ +	nodemask = cpumask_of_node(cpu); +	for (cpu = cpumask_first_and(nodemask, mask); cpu < nr_cpu_ids; +	     cpu = cpumask_next_and(cpu, nodemask, mask)) { +		if (cpu_online(cpu)) +			goto call; +	} + +	/* Any online will do: smp_call_function_single handles nr_cpu_ids. */ +	cpu = cpumask_any_and(mask, cpu_online_mask); +call: +	ret = smp_call_function_single(cpu, func, info, wait); +	put_cpu(); +	return ret; +} +EXPORT_SYMBOL_GPL(smp_call_function_any); +  /**   * __smp_call_function_single(): Run a function on another CPU   * @cpu: The CPU to run on. @@ -355,9 +398,7 @@ void __smp_call_function_single(int cpu, struct call_single_data *data,   * @wait: If true, wait (atomically) until function has completed   *        on other CPUs.   * - * If @wait is true, then returns once @func has returned. Note that @wait - * will be implicitly turned on in case of allocation failures, since - * we fall back to on-stack allocation. + * If @wait is true, then returns once @func has returned.   *   * You must not call this function with disabled interrupts or from a   * hardware interrupt handler or from a bottom half handler. Preemption @@ -443,8 +484,7 @@ EXPORT_SYMBOL(smp_call_function_many);   * Returns 0.   *   * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. In case of allocation - * failure, @wait will be implicitly turned on. + * it returns just before the target cpu calls @func.   *   * You must not call this function with disabled interrupts or from a   * hardware interrupt handler or from a bottom half handler. diff --git a/kernel/softirq.c b/kernel/softirq.c index f8749e5216e..21939d9e830 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -302,9 +302,9 @@ void irq_exit(void)  	if (!in_interrupt() && local_softirq_pending())  		invoke_softirq(); +	rcu_irq_exit();  #ifdef CONFIG_NO_HZ  	/* Make sure that timer wheel updates are propagated */ -	rcu_irq_exit();  	if (idle_cpu(smp_processor_id()) && !in_interrupt() && !need_resched())  		tick_nohz_stop_sched_tick(0);  #endif diff --git a/kernel/spinlock.c b/kernel/spinlock.c index 5ddab730cb2..41e042219ff 100644 --- a/kernel/spinlock.c +++ b/kernel/spinlock.c @@ -21,145 +21,28 @@  #include <linux/debug_locks.h>  #include <linux/module.h> -#ifndef _spin_trylock -int __lockfunc _spin_trylock(spinlock_t *lock) -{ -	return __spin_trylock(lock); -} -EXPORT_SYMBOL(_spin_trylock); -#endif - -#ifndef _read_trylock -int __lockfunc _read_trylock(rwlock_t *lock) -{ -	return __read_trylock(lock); -} -EXPORT_SYMBOL(_read_trylock); -#endif - -#ifndef _write_trylock -int __lockfunc _write_trylock(rwlock_t *lock) -{ -	return __write_trylock(lock); -} -EXPORT_SYMBOL(_write_trylock); -#endif -  /*   * If lockdep is enabled then we use the non-preemption spin-ops   * even on CONFIG_PREEMPT, because lockdep assumes that interrupts are   * not re-enabled during lock-acquire (which the preempt-spin-ops do):   */  #if !defined(CONFIG_GENERIC_LOCKBREAK) || defined(CONFIG_DEBUG_LOCK_ALLOC) - -#ifndef _read_lock -void __lockfunc _read_lock(rwlock_t *lock) -{ -	__read_lock(lock); -} -EXPORT_SYMBOL(_read_lock); -#endif - -#ifndef _spin_lock_irqsave -unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock) -{ -	return __spin_lock_irqsave(lock); -} -EXPORT_SYMBOL(_spin_lock_irqsave); -#endif - -#ifndef _spin_lock_irq -void __lockfunc _spin_lock_irq(spinlock_t *lock) -{ -	__spin_lock_irq(lock); -} -EXPORT_SYMBOL(_spin_lock_irq); -#endif - -#ifndef _spin_lock_bh -void __lockfunc _spin_lock_bh(spinlock_t *lock) -{ -	__spin_lock_bh(lock); -} -EXPORT_SYMBOL(_spin_lock_bh); -#endif - -#ifndef _read_lock_irqsave -unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock) -{ -	return __read_lock_irqsave(lock); -} -EXPORT_SYMBOL(_read_lock_irqsave); -#endif - -#ifndef _read_lock_irq -void __lockfunc _read_lock_irq(rwlock_t *lock) -{ -	__read_lock_irq(lock); -} -EXPORT_SYMBOL(_read_lock_irq); -#endif - -#ifndef _read_lock_bh -void __lockfunc _read_lock_bh(rwlock_t *lock) -{ -	__read_lock_bh(lock); -} -EXPORT_SYMBOL(_read_lock_bh); -#endif - -#ifndef _write_lock_irqsave -unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock) -{ -	return __write_lock_irqsave(lock); -} -EXPORT_SYMBOL(_write_lock_irqsave); -#endif - -#ifndef _write_lock_irq -void __lockfunc _write_lock_irq(rwlock_t *lock) -{ -	__write_lock_irq(lock); -} -EXPORT_SYMBOL(_write_lock_irq); -#endif - -#ifndef _write_lock_bh -void __lockfunc _write_lock_bh(rwlock_t *lock) -{ -	__write_lock_bh(lock); -} -EXPORT_SYMBOL(_write_lock_bh); -#endif - -#ifndef _spin_lock -void __lockfunc _spin_lock(spinlock_t *lock) -{ -	__spin_lock(lock); -} -EXPORT_SYMBOL(_spin_lock); -#endif - -#ifndef _write_lock -void __lockfunc _write_lock(rwlock_t *lock) -{ -	__write_lock(lock); -} -EXPORT_SYMBOL(_write_lock); -#endif - -#else /* CONFIG_PREEMPT: */ -  /* + * The __lock_function inlines are taken from + * include/linux/spinlock_api_smp.h + */ +#else +/* + * We build the __lock_function inlines here. They are too large for + * inlining all over the place, but here is only one user per function + * which embedds them into the calling _lock_function below. + *   * This could be a long-held lock. We both prepare to spin for a long   * time (making _this_ CPU preemptable if possible), and we also signal   * towards that other CPU that it should break the lock ASAP. - * - * (We do this in a function because inlining it would be excessive.)   */ -  #define BUILD_LOCK_OPS(op, locktype)					\ -void __lockfunc _##op##_lock(locktype##_t *lock)			\ +void __lockfunc __##op##_lock(locktype##_t *lock)			\  {									\  	for (;;) {							\  		preempt_disable();					\ @@ -175,9 +58,7 @@ void __lockfunc _##op##_lock(locktype##_t *lock)			\  	(lock)->break_lock = 0;						\  }									\  									\ -EXPORT_SYMBOL(_##op##_lock);						\ -									\ -unsigned long __lockfunc _##op##_lock_irqsave(locktype##_t *lock)	\ +unsigned long __lockfunc __##op##_lock_irqsave(locktype##_t *lock)	\  {									\  	unsigned long flags;						\  									\ @@ -198,16 +79,12 @@ unsigned long __lockfunc _##op##_lock_irqsave(locktype##_t *lock)	\  	return flags;							\  }									\  									\ -EXPORT_SYMBOL(_##op##_lock_irqsave);					\ -									\ -void __lockfunc _##op##_lock_irq(locktype##_t *lock)			\ +void __lockfunc __##op##_lock_irq(locktype##_t *lock)			\  {									\  	_##op##_lock_irqsave(lock);					\  }									\  									\ -EXPORT_SYMBOL(_##op##_lock_irq);					\ -									\ -void __lockfunc _##op##_lock_bh(locktype##_t *lock)			\ +void __lockfunc __##op##_lock_bh(locktype##_t *lock)			\  {									\  	unsigned long flags;						\  									\ @@ -220,23 +97,21 @@ void __lockfunc _##op##_lock_bh(locktype##_t *lock)			\  	local_bh_disable();						\  	local_irq_restore(flags);					\  }									\ -									\ -EXPORT_SYMBOL(_##op##_lock_bh)  /*   * Build preemption-friendly versions of the following   * lock-spinning functions:   * - *         _[spin|read|write]_lock() - *         _[spin|read|write]_lock_irq() - *         _[spin|read|write]_lock_irqsave() - *         _[spin|read|write]_lock_bh() + *         __[spin|read|write]_lock() + *         __[spin|read|write]_lock_irq() + *         __[spin|read|write]_lock_irqsave() + *         __[spin|read|write]_lock_bh()   */  BUILD_LOCK_OPS(spin, spinlock);  BUILD_LOCK_OPS(read, rwlock);  BUILD_LOCK_OPS(write, rwlock); -#endif /* CONFIG_PREEMPT */ +#endif  #ifdef CONFIG_DEBUG_LOCK_ALLOC @@ -248,7 +123,8 @@ void __lockfunc _spin_lock_nested(spinlock_t *lock, int subclass)  }  EXPORT_SYMBOL(_spin_lock_nested); -unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, int subclass) +unsigned long __lockfunc _spin_lock_irqsave_nested(spinlock_t *lock, +						   int subclass)  {  	unsigned long flags; @@ -272,7 +148,127 @@ EXPORT_SYMBOL(_spin_lock_nest_lock);  #endif -#ifndef _spin_unlock +#ifndef CONFIG_INLINE_SPIN_TRYLOCK +int __lockfunc _spin_trylock(spinlock_t *lock) +{ +	return __spin_trylock(lock); +} +EXPORT_SYMBOL(_spin_trylock); +#endif + +#ifndef CONFIG_INLINE_READ_TRYLOCK +int __lockfunc _read_trylock(rwlock_t *lock) +{ +	return __read_trylock(lock); +} +EXPORT_SYMBOL(_read_trylock); +#endif + +#ifndef CONFIG_INLINE_WRITE_TRYLOCK +int __lockfunc _write_trylock(rwlock_t *lock) +{ +	return __write_trylock(lock); +} +EXPORT_SYMBOL(_write_trylock); +#endif + +#ifndef CONFIG_INLINE_READ_LOCK +void __lockfunc _read_lock(rwlock_t *lock) +{ +	__read_lock(lock); +} +EXPORT_SYMBOL(_read_lock); +#endif + +#ifndef CONFIG_INLINE_SPIN_LOCK_IRQSAVE +unsigned long __lockfunc _spin_lock_irqsave(spinlock_t *lock) +{ +	return __spin_lock_irqsave(lock); +} +EXPORT_SYMBOL(_spin_lock_irqsave); +#endif + +#ifndef CONFIG_INLINE_SPIN_LOCK_IRQ +void __lockfunc _spin_lock_irq(spinlock_t *lock) +{ +	__spin_lock_irq(lock); +} +EXPORT_SYMBOL(_spin_lock_irq); +#endif + +#ifndef CONFIG_INLINE_SPIN_LOCK_BH +void __lockfunc _spin_lock_bh(spinlock_t *lock) +{ +	__spin_lock_bh(lock); +} +EXPORT_SYMBOL(_spin_lock_bh); +#endif + +#ifndef CONFIG_INLINE_READ_LOCK_IRQSAVE +unsigned long __lockfunc _read_lock_irqsave(rwlock_t *lock) +{ +	return __read_lock_irqsave(lock); +} +EXPORT_SYMBOL(_read_lock_irqsave); +#endif + +#ifndef CONFIG_INLINE_READ_LOCK_IRQ +void __lockfunc _read_lock_irq(rwlock_t *lock) +{ +	__read_lock_irq(lock); +} +EXPORT_SYMBOL(_read_lock_irq); +#endif + +#ifndef CONFIG_INLINE_READ_LOCK_BH +void __lockfunc _read_lock_bh(rwlock_t *lock) +{ +	__read_lock_bh(lock); +} +EXPORT_SYMBOL(_read_lock_bh); +#endif + +#ifndef CONFIG_INLINE_WRITE_LOCK_IRQSAVE +unsigned long __lockfunc _write_lock_irqsave(rwlock_t *lock) +{ +	return __write_lock_irqsave(lock); +} +EXPORT_SYMBOL(_write_lock_irqsave); +#endif + +#ifndef CONFIG_INLINE_WRITE_LOCK_IRQ +void __lockfunc _write_lock_irq(rwlock_t *lock) +{ +	__write_lock_irq(lock); +} +EXPORT_SYMBOL(_write_lock_irq); +#endif + +#ifndef CONFIG_INLINE_WRITE_LOCK_BH +void __lockfunc _write_lock_bh(rwlock_t *lock) +{ +	__write_lock_bh(lock); +} +EXPORT_SYMBOL(_write_lock_bh); +#endif + +#ifndef CONFIG_INLINE_SPIN_LOCK +void __lockfunc _spin_lock(spinlock_t *lock) +{ +	__spin_lock(lock); +} +EXPORT_SYMBOL(_spin_lock); +#endif + +#ifndef CONFIG_INLINE_WRITE_LOCK +void __lockfunc _write_lock(rwlock_t *lock) +{ +	__write_lock(lock); +} +EXPORT_SYMBOL(_write_lock); +#endif + +#ifndef CONFIG_INLINE_SPIN_UNLOCK  void __lockfunc _spin_unlock(spinlock_t *lock)  {  	__spin_unlock(lock); @@ -280,7 +276,7 @@ void __lockfunc _spin_unlock(spinlock_t *lock)  EXPORT_SYMBOL(_spin_unlock);  #endif -#ifndef _write_unlock +#ifndef CONFIG_INLINE_WRITE_UNLOCK  void __lockfunc _write_unlock(rwlock_t *lock)  {  	__write_unlock(lock); @@ -288,7 +284,7 @@ void __lockfunc _write_unlock(rwlock_t *lock)  EXPORT_SYMBOL(_write_unlock);  #endif -#ifndef _read_unlock +#ifndef CONFIG_INLINE_READ_UNLOCK  void __lockfunc _read_unlock(rwlock_t *lock)  {  	__read_unlock(lock); @@ -296,7 +292,7 @@ void __lockfunc _read_unlock(rwlock_t *lock)  EXPORT_SYMBOL(_read_unlock);  #endif -#ifndef _spin_unlock_irqrestore +#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE  void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)  {  	__spin_unlock_irqrestore(lock, flags); @@ -304,7 +300,7 @@ void __lockfunc _spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)  EXPORT_SYMBOL(_spin_unlock_irqrestore);  #endif -#ifndef _spin_unlock_irq +#ifndef CONFIG_INLINE_SPIN_UNLOCK_IRQ  void __lockfunc _spin_unlock_irq(spinlock_t *lock)  {  	__spin_unlock_irq(lock); @@ -312,7 +308,7 @@ void __lockfunc _spin_unlock_irq(spinlock_t *lock)  EXPORT_SYMBOL(_spin_unlock_irq);  #endif -#ifndef _spin_unlock_bh +#ifndef CONFIG_INLINE_SPIN_UNLOCK_BH  void __lockfunc _spin_unlock_bh(spinlock_t *lock)  {  	__spin_unlock_bh(lock); @@ -320,7 +316,7 @@ void __lockfunc _spin_unlock_bh(spinlock_t *lock)  EXPORT_SYMBOL(_spin_unlock_bh);  #endif -#ifndef _read_unlock_irqrestore +#ifndef CONFIG_INLINE_READ_UNLOCK_IRQRESTORE  void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  {  	__read_unlock_irqrestore(lock, flags); @@ -328,7 +324,7 @@ void __lockfunc _read_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  EXPORT_SYMBOL(_read_unlock_irqrestore);  #endif -#ifndef _read_unlock_irq +#ifndef CONFIG_INLINE_READ_UNLOCK_IRQ  void __lockfunc _read_unlock_irq(rwlock_t *lock)  {  	__read_unlock_irq(lock); @@ -336,7 +332,7 @@ void __lockfunc _read_unlock_irq(rwlock_t *lock)  EXPORT_SYMBOL(_read_unlock_irq);  #endif -#ifndef _read_unlock_bh +#ifndef CONFIG_INLINE_READ_UNLOCK_BH  void __lockfunc _read_unlock_bh(rwlock_t *lock)  {  	__read_unlock_bh(lock); @@ -344,7 +340,7 @@ void __lockfunc _read_unlock_bh(rwlock_t *lock)  EXPORT_SYMBOL(_read_unlock_bh);  #endif -#ifndef _write_unlock_irqrestore +#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE  void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  {  	__write_unlock_irqrestore(lock, flags); @@ -352,7 +348,7 @@ void __lockfunc _write_unlock_irqrestore(rwlock_t *lock, unsigned long flags)  EXPORT_SYMBOL(_write_unlock_irqrestore);  #endif -#ifndef _write_unlock_irq +#ifndef CONFIG_INLINE_WRITE_UNLOCK_IRQ  void __lockfunc _write_unlock_irq(rwlock_t *lock)  {  	__write_unlock_irq(lock); @@ -360,7 +356,7 @@ void __lockfunc _write_unlock_irq(rwlock_t *lock)  EXPORT_SYMBOL(_write_unlock_irq);  #endif -#ifndef _write_unlock_bh +#ifndef CONFIG_INLINE_WRITE_UNLOCK_BH  void __lockfunc _write_unlock_bh(rwlock_t *lock)  {  	__write_unlock_bh(lock); @@ -368,7 +364,7 @@ void __lockfunc _write_unlock_bh(rwlock_t *lock)  EXPORT_SYMBOL(_write_unlock_bh);  #endif -#ifndef _spin_trylock_bh +#ifndef CONFIG_INLINE_SPIN_TRYLOCK_BH  int __lockfunc _spin_trylock_bh(spinlock_t *lock)  {  	return __spin_trylock_bh(lock); diff --git a/kernel/srcu.c b/kernel/srcu.c index b0aeeaf22ce..818d7d9aa03 100644 --- a/kernel/srcu.c +++ b/kernel/srcu.c @@ -49,6 +49,7 @@ int init_srcu_struct(struct srcu_struct *sp)  	sp->per_cpu_ref = alloc_percpu(struct srcu_struct_array);  	return (sp->per_cpu_ref ? 0 : -ENOMEM);  } +EXPORT_SYMBOL_GPL(init_srcu_struct);  /*   * srcu_readers_active_idx -- returns approximate number of readers @@ -97,6 +98,7 @@ void cleanup_srcu_struct(struct srcu_struct *sp)  	free_percpu(sp->per_cpu_ref);  	sp->per_cpu_ref = NULL;  } +EXPORT_SYMBOL_GPL(cleanup_srcu_struct);  /**   * srcu_read_lock - register a new reader for an SRCU-protected structure. @@ -118,6 +120,7 @@ int srcu_read_lock(struct srcu_struct *sp)  	preempt_enable();  	return idx;  } +EXPORT_SYMBOL_GPL(srcu_read_lock);  /**   * srcu_read_unlock - unregister a old reader from an SRCU-protected structure. @@ -136,22 +139,12 @@ void srcu_read_unlock(struct srcu_struct *sp, int idx)  	per_cpu_ptr(sp->per_cpu_ref, smp_processor_id())->c[idx]--;  	preempt_enable();  } +EXPORT_SYMBOL_GPL(srcu_read_unlock); -/** - * synchronize_srcu - wait for prior SRCU read-side critical-section completion - * @sp: srcu_struct with which to synchronize. - * - * Flip the completed counter, and wait for the old count to drain to zero. - * As with classic RCU, the updater must use some separate means of - * synchronizing concurrent updates.  Can block; must be called from - * process context. - * - * Note that it is illegal to call synchornize_srcu() from the corresponding - * SRCU read-side critical section; doing so will result in deadlock. - * However, it is perfectly legal to call synchronize_srcu() on one - * srcu_struct from some other srcu_struct's read-side critical section. +/* + * Helper function for synchronize_srcu() and synchronize_srcu_expedited().   */ -void synchronize_srcu(struct srcu_struct *sp) +void __synchronize_srcu(struct srcu_struct *sp, void (*sync_func)(void))  {  	int idx; @@ -173,7 +166,7 @@ void synchronize_srcu(struct srcu_struct *sp)  		return;  	} -	synchronize_sched();  /* Force memory barrier on all CPUs. */ +	sync_func();  /* Force memory barrier on all CPUs. */  	/*  	 * The preceding synchronize_sched() ensures that any CPU that @@ -190,7 +183,7 @@ void synchronize_srcu(struct srcu_struct *sp)  	idx = sp->completed & 0x1;  	sp->completed++; -	synchronize_sched();  /* Force memory barrier on all CPUs. */ +	sync_func();  /* Force memory barrier on all CPUs. */  	/*  	 * At this point, because of the preceding synchronize_sched(), @@ -203,7 +196,7 @@ void synchronize_srcu(struct srcu_struct *sp)  	while (srcu_readers_active_idx(sp, idx))  		schedule_timeout_interruptible(1); -	synchronize_sched();  /* Force memory barrier on all CPUs. */ +	sync_func();  /* Force memory barrier on all CPUs. */  	/*  	 * The preceding synchronize_sched() forces all srcu_read_unlock() @@ -237,6 +230,47 @@ void synchronize_srcu(struct srcu_struct *sp)  }  /** + * synchronize_srcu - wait for prior SRCU read-side critical-section completion + * @sp: srcu_struct with which to synchronize. + * + * Flip the completed counter, and wait for the old count to drain to zero. + * As with classic RCU, the updater must use some separate means of + * synchronizing concurrent updates.  Can block; must be called from + * process context. + * + * Note that it is illegal to call synchronize_srcu() from the corresponding + * SRCU read-side critical section; doing so will result in deadlock. + * However, it is perfectly legal to call synchronize_srcu() on one + * srcu_struct from some other srcu_struct's read-side critical section. + */ +void synchronize_srcu(struct srcu_struct *sp) +{ +	__synchronize_srcu(sp, synchronize_sched); +} +EXPORT_SYMBOL_GPL(synchronize_srcu); + +/** + * synchronize_srcu_expedited - like synchronize_srcu, but less patient + * @sp: srcu_struct with which to synchronize. + * + * Flip the completed counter, and wait for the old count to drain to zero. + * As with classic RCU, the updater must use some separate means of + * synchronizing concurrent updates.  Can block; must be called from + * process context. + * + * Note that it is illegal to call synchronize_srcu_expedited() + * from the corresponding SRCU read-side critical section; doing so + * will result in deadlock.  However, it is perfectly legal to call + * synchronize_srcu_expedited() on one srcu_struct from some other + * srcu_struct's read-side critical section. + */ +void synchronize_srcu_expedited(struct srcu_struct *sp) +{ +	__synchronize_srcu(sp, synchronize_sched_expedited); +} +EXPORT_SYMBOL_GPL(synchronize_srcu_expedited); + +/**   * srcu_batches_completed - return batches completed.   * @sp: srcu_struct on which to report batch completion.   * @@ -248,10 +282,4 @@ long srcu_batches_completed(struct srcu_struct *sp)  {  	return sp->completed;  } - -EXPORT_SYMBOL_GPL(init_srcu_struct); -EXPORT_SYMBOL_GPL(cleanup_srcu_struct); -EXPORT_SYMBOL_GPL(srcu_read_lock); -EXPORT_SYMBOL_GPL(srcu_read_unlock); -EXPORT_SYMBOL_GPL(synchronize_srcu);  EXPORT_SYMBOL_GPL(srcu_batches_completed); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 0d949c51741..4dbf93a52ee 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -36,6 +36,7 @@  #include <linux/sysrq.h>  #include <linux/highuid.h>  #include <linux/writeback.h> +#include <linux/ratelimit.h>  #include <linux/hugetlb.h>  #include <linux/initrd.h>  #include <linux/key.h> @@ -158,6 +159,8 @@ extern int no_unaligned_warning;  extern int unaligned_dump_stack;  #endif +extern struct ratelimit_state printk_ratelimit_state; +  #ifdef CONFIG_RT_MUTEXES  extern int max_lock_depth;  #endif diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6dc4e5ef7a0..e51a1bcb7be 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -60,6 +60,13 @@ static int last_ftrace_enabled;  /* Quick disabling of function tracer. */  int function_trace_stop; +/* List for set_ftrace_pid's pids. */ +LIST_HEAD(ftrace_pids); +struct ftrace_pid { +	struct list_head list; +	struct pid *pid; +}; +  /*   * ftrace_disabled is set when an anomaly is discovered.   * ftrace_disabled is much stronger than ftrace_enabled. @@ -78,6 +85,10 @@ ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;  ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;  ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub; +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +static int ftrace_set_func(unsigned long *array, int *idx, char *buffer); +#endif +  static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)  {  	struct ftrace_ops *op = ftrace_list; @@ -155,7 +166,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops)  		else  			func = ftrace_list_func; -		if (ftrace_pid_trace) { +		if (!list_empty(&ftrace_pids)) {  			set_ftrace_pid_function(func);  			func = ftrace_pid_func;  		} @@ -203,7 +214,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops)  		if (ftrace_list->next == &ftrace_list_end) {  			ftrace_func_t func = ftrace_list->func; -			if (ftrace_pid_trace) { +			if (!list_empty(&ftrace_pids)) {  				set_ftrace_pid_function(func);  				func = ftrace_pid_func;  			} @@ -231,7 +242,7 @@ static void ftrace_update_pid_func(void)  	func = __ftrace_trace_function;  #endif -	if (ftrace_pid_trace) { +	if (!list_empty(&ftrace_pids)) {  		set_ftrace_pid_function(func);  		func = ftrace_pid_func;  	} else { @@ -821,8 +832,6 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer)  }  #endif /* CONFIG_FUNCTION_PROFILER */ -/* set when tracing only a pid */ -struct pid *ftrace_pid_trace;  static struct pid * const ftrace_swapper_pid = &init_struct_pid;  #ifdef CONFIG_DYNAMIC_FTRACE @@ -1261,12 +1270,34 @@ static int ftrace_update_code(struct module *mod)  		ftrace_new_addrs = p->newlist;  		p->flags = 0L; -		/* convert record (i.e, patch mcount-call with NOP) */ -		if (ftrace_code_disable(mod, p)) { -			p->flags |= FTRACE_FL_CONVERTED; -			ftrace_update_cnt++; -		} else +		/* +		 * Do the initial record convertion from mcount jump +		 * to the NOP instructions. +		 */ +		if (!ftrace_code_disable(mod, p)) {  			ftrace_free_rec(p); +			continue; +		} + +		p->flags |= FTRACE_FL_CONVERTED; +		ftrace_update_cnt++; + +		/* +		 * If the tracing is enabled, go ahead and enable the record. +		 * +		 * The reason not to enable the record immediatelly is the +		 * inherent check of ftrace_make_nop/ftrace_make_call for +		 * correct previous instructions.  Making first the NOP +		 * conversion puts the module to the correct state, thus +		 * passing the ftrace_make_call check. +		 */ +		if (ftrace_start_up) { +			int failed = __ftrace_replace_code(p, 1); +			if (failed) { +				ftrace_bug(failed, p->ip); +				ftrace_free_rec(p); +			} +		}  	}  	stop = ftrace_now(raw_smp_processor_id()); @@ -1656,60 +1687,6 @@ ftrace_regex_lseek(struct file *file, loff_t offset, int origin)  	return ret;  } -enum { -	MATCH_FULL, -	MATCH_FRONT_ONLY, -	MATCH_MIDDLE_ONLY, -	MATCH_END_ONLY, -}; - -/* - * (static function - no need for kernel doc) - * - * Pass in a buffer containing a glob and this function will - * set search to point to the search part of the buffer and - * return the type of search it is (see enum above). - * This does modify buff. - * - * Returns enum type. - *  search returns the pointer to use for comparison. - *  not returns 1 if buff started with a '!' - *     0 otherwise. - */ -static int -ftrace_setup_glob(char *buff, int len, char **search, int *not) -{ -	int type = MATCH_FULL; -	int i; - -	if (buff[0] == '!') { -		*not = 1; -		buff++; -		len--; -	} else -		*not = 0; - -	*search = buff; - -	for (i = 0; i < len; i++) { -		if (buff[i] == '*') { -			if (!i) { -				*search = buff + 1; -				type = MATCH_END_ONLY; -			} else { -				if (type == MATCH_END_ONLY) -					type = MATCH_MIDDLE_ONLY; -				else -					type = MATCH_FRONT_ONLY; -				buff[i] = 0; -				break; -			} -		} -	} - -	return type; -} -  static int ftrace_match(char *str, char *regex, int len, int type)  {  	int matched = 0; @@ -1758,7 +1735,7 @@ static void ftrace_match_records(char *buff, int len, int enable)  	int not;  	flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE; -	type = ftrace_setup_glob(buff, len, &search, ¬); +	type = filter_parse_regex(buff, len, &search, ¬);  	search_len = strlen(search); @@ -1826,7 +1803,7 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable)  	}  	if (strlen(buff)) { -		type = ftrace_setup_glob(buff, strlen(buff), &search, ¬); +		type = filter_parse_regex(buff, strlen(buff), &search, ¬);  		search_len = strlen(search);  	} @@ -1991,7 +1968,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,  	int count = 0;  	char *search; -	type = ftrace_setup_glob(glob, strlen(glob), &search, ¬); +	type = filter_parse_regex(glob, strlen(glob), &search, ¬);  	len = strlen(search);  	/* we do not support '!' for function probes */ @@ -2068,7 +2045,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,  	else if (glob) {  		int not; -		type = ftrace_setup_glob(glob, strlen(glob), &search, ¬); +		type = filter_parse_regex(glob, strlen(glob), &search, ¬);  		len = strlen(search);  		/* we do not support '!' for function probes */ @@ -2312,6 +2289,32 @@ static int __init set_ftrace_filter(char *str)  }  __setup("ftrace_filter=", set_ftrace_filter); +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata; +static int __init set_graph_function(char *str) +{ +	strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE); +	return 1; +} +__setup("ftrace_graph_filter=", set_graph_function); + +static void __init set_ftrace_early_graph(char *buf) +{ +	int ret; +	char *func; + +	while (buf) { +		func = strsep(&buf, ","); +		/* we allow only one expression at a time */ +		ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count, +				      func); +		if (ret) +			printk(KERN_DEBUG "ftrace: function %s not " +					  "traceable\n", func); +	} +} +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ +  static void __init set_ftrace_early_filter(char *buf, int enable)  {  	char *func; @@ -2328,6 +2331,10 @@ static void __init set_ftrace_early_filters(void)  		set_ftrace_early_filter(ftrace_filter_buf, 1);  	if (ftrace_notrace_buf[0])  		set_ftrace_early_filter(ftrace_notrace_buf, 0); +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +	if (ftrace_graph_buf[0]) +		set_ftrace_early_graph(ftrace_graph_buf); +#endif /* CONFIG_FUNCTION_GRAPH_TRACER */  }  static int @@ -2513,7 +2520,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer)  		return -ENODEV;  	/* decode regex */ -	type = ftrace_setup_glob(buffer, strlen(buffer), &search, ¬); +	type = filter_parse_regex(buffer, strlen(buffer), &search, ¬);  	if (not)  		return -EINVAL; @@ -2624,7 +2631,7 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer)  	return 0;  } -static int ftrace_convert_nops(struct module *mod, +static int ftrace_process_locs(struct module *mod,  			       unsigned long *start,  			       unsigned long *end)  { @@ -2684,7 +2691,7 @@ static void ftrace_init_module(struct module *mod,  {  	if (ftrace_disabled || start == end)  		return; -	ftrace_convert_nops(mod, start, end); +	ftrace_process_locs(mod, start, end);  }  static int ftrace_module_notify(struct notifier_block *self, @@ -2745,7 +2752,7 @@ void __init ftrace_init(void)  	last_ftrace_enabled = ftrace_enabled = 1; -	ret = ftrace_convert_nops(NULL, +	ret = ftrace_process_locs(NULL,  				  __start_mcount_loc,  				  __stop_mcount_loc); @@ -2778,23 +2785,6 @@ static inline void ftrace_startup_enable(int command) { }  # define ftrace_shutdown_sysctl()	do { } while (0)  #endif /* CONFIG_DYNAMIC_FTRACE */ -static ssize_t -ftrace_pid_read(struct file *file, char __user *ubuf, -		       size_t cnt, loff_t *ppos) -{ -	char buf[64]; -	int r; - -	if (ftrace_pid_trace == ftrace_swapper_pid) -		r = sprintf(buf, "swapper tasks\n"); -	else if (ftrace_pid_trace) -		r = sprintf(buf, "%u\n", pid_vnr(ftrace_pid_trace)); -	else -		r = sprintf(buf, "no pid\n"); - -	return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); -} -  static void clear_ftrace_swapper(void)  {  	struct task_struct *p; @@ -2845,14 +2835,12 @@ static void set_ftrace_pid(struct pid *pid)  	rcu_read_unlock();  } -static void clear_ftrace_pid_task(struct pid **pid) +static void clear_ftrace_pid_task(struct pid *pid)  { -	if (*pid == ftrace_swapper_pid) +	if (pid == ftrace_swapper_pid)  		clear_ftrace_swapper();  	else -		clear_ftrace_pid(*pid); - -	*pid = NULL; +		clear_ftrace_pid(pid);  }  static void set_ftrace_pid_task(struct pid *pid) @@ -2863,74 +2851,184 @@ static void set_ftrace_pid_task(struct pid *pid)  		set_ftrace_pid(pid);  } -static ssize_t -ftrace_pid_write(struct file *filp, const char __user *ubuf, -		   size_t cnt, loff_t *ppos) +static int ftrace_pid_add(int p)  {  	struct pid *pid; -	char buf[64]; -	long val; -	int ret; +	struct ftrace_pid *fpid; +	int ret = -EINVAL; -	if (cnt >= sizeof(buf)) -		return -EINVAL; +	mutex_lock(&ftrace_lock); -	if (copy_from_user(&buf, ubuf, cnt)) -		return -EFAULT; +	if (!p) +		pid = ftrace_swapper_pid; +	else +		pid = find_get_pid(p); -	buf[cnt] = 0; +	if (!pid) +		goto out; -	ret = strict_strtol(buf, 10, &val); -	if (ret < 0) -		return ret; +	ret = 0; -	mutex_lock(&ftrace_lock); -	if (val < 0) { -		/* disable pid tracing */ -		if (!ftrace_pid_trace) -			goto out; +	list_for_each_entry(fpid, &ftrace_pids, list) +		if (fpid->pid == pid) +			goto out_put; -		clear_ftrace_pid_task(&ftrace_pid_trace); +	ret = -ENOMEM; -	} else { -		/* swapper task is special */ -		if (!val) { -			pid = ftrace_swapper_pid; -			if (pid == ftrace_pid_trace) -				goto out; -		} else { -			pid = find_get_pid(val); +	fpid = kmalloc(sizeof(*fpid), GFP_KERNEL); +	if (!fpid) +		goto out_put; -			if (pid == ftrace_pid_trace) { -				put_pid(pid); -				goto out; -			} -		} +	list_add(&fpid->list, &ftrace_pids); +	fpid->pid = pid; -		if (ftrace_pid_trace) -			clear_ftrace_pid_task(&ftrace_pid_trace); +	set_ftrace_pid_task(pid); -		if (!pid) -			goto out; +	ftrace_update_pid_func(); +	ftrace_startup_enable(0); + +	mutex_unlock(&ftrace_lock); +	return 0; -		ftrace_pid_trace = pid; +out_put: +	if (pid != ftrace_swapper_pid) +		put_pid(pid); -		set_ftrace_pid_task(ftrace_pid_trace); +out: +	mutex_unlock(&ftrace_lock); +	return ret; +} + +static void ftrace_pid_reset(void) +{ +	struct ftrace_pid *fpid, *safe; + +	mutex_lock(&ftrace_lock); +	list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) { +		struct pid *pid = fpid->pid; + +		clear_ftrace_pid_task(pid); + +		list_del(&fpid->list); +		kfree(fpid);  	} -	/* update the function call */  	ftrace_update_pid_func();  	ftrace_startup_enable(0); - out:  	mutex_unlock(&ftrace_lock); +} -	return cnt; +static void *fpid_start(struct seq_file *m, loff_t *pos) +{ +	mutex_lock(&ftrace_lock); + +	if (list_empty(&ftrace_pids) && (!*pos)) +		return (void *) 1; + +	return seq_list_start(&ftrace_pids, *pos); +} + +static void *fpid_next(struct seq_file *m, void *v, loff_t *pos) +{ +	if (v == (void *)1) +		return NULL; + +	return seq_list_next(v, &ftrace_pids, pos); +} + +static void fpid_stop(struct seq_file *m, void *p) +{ +	mutex_unlock(&ftrace_lock); +} + +static int fpid_show(struct seq_file *m, void *v) +{ +	const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list); + +	if (v == (void *)1) { +		seq_printf(m, "no pid\n"); +		return 0; +	} + +	if (fpid->pid == ftrace_swapper_pid) +		seq_printf(m, "swapper tasks\n"); +	else +		seq_printf(m, "%u\n", pid_vnr(fpid->pid)); + +	return 0; +} + +static const struct seq_operations ftrace_pid_sops = { +	.start = fpid_start, +	.next = fpid_next, +	.stop = fpid_stop, +	.show = fpid_show, +}; + +static int +ftrace_pid_open(struct inode *inode, struct file *file) +{ +	int ret = 0; + +	if ((file->f_mode & FMODE_WRITE) && +	    (file->f_flags & O_TRUNC)) +		ftrace_pid_reset(); + +	if (file->f_mode & FMODE_READ) +		ret = seq_open(file, &ftrace_pid_sops); + +	return ret; +} + +static ssize_t +ftrace_pid_write(struct file *filp, const char __user *ubuf, +		   size_t cnt, loff_t *ppos) +{ +	char buf[64], *tmp; +	long val; +	int ret; + +	if (cnt >= sizeof(buf)) +		return -EINVAL; + +	if (copy_from_user(&buf, ubuf, cnt)) +		return -EFAULT; + +	buf[cnt] = 0; + +	/* +	 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid" +	 * to clean the filter quietly. +	 */ +	tmp = strstrip(buf); +	if (strlen(tmp) == 0) +		return 1; + +	ret = strict_strtol(tmp, 10, &val); +	if (ret < 0) +		return ret; + +	ret = ftrace_pid_add(val); + +	return ret ? ret : cnt; +} + +static int +ftrace_pid_release(struct inode *inode, struct file *file) +{ +	if (file->f_mode & FMODE_READ) +		seq_release(inode, file); + +	return 0;  }  static const struct file_operations ftrace_pid_fops = { -	.read = ftrace_pid_read, -	.write = ftrace_pid_write, +	.open		= ftrace_pid_open, +	.write		= ftrace_pid_write, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= ftrace_pid_release,  };  static __init int ftrace_init_debugfs(void) @@ -3293,4 +3391,3 @@ void ftrace_graph_stop(void)  	ftrace_stop();  }  #endif - diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 5dd017fea6f..a72c6e03dee 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1787,9 +1787,9 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer,  static struct ring_buffer_event *  rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,  	     unsigned long length, unsigned long tail, -	     struct buffer_page *commit_page,  	     struct buffer_page *tail_page, u64 *ts)  { +	struct buffer_page *commit_page = cpu_buffer->commit_page;  	struct ring_buffer *buffer = cpu_buffer->buffer;  	struct buffer_page *next_page;  	int ret; @@ -1892,13 +1892,10 @@ static struct ring_buffer_event *  __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,  		  unsigned type, unsigned long length, u64 *ts)  { -	struct buffer_page *tail_page, *commit_page; +	struct buffer_page *tail_page;  	struct ring_buffer_event *event;  	unsigned long tail, write; -	commit_page = cpu_buffer->commit_page; -	/* we just need to protect against interrupts */ -	barrier();  	tail_page = cpu_buffer->tail_page;  	write = local_add_return(length, &tail_page->write); @@ -1909,7 +1906,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,  	/* See if we shot pass the end of this buffer page */  	if (write > BUF_PAGE_SIZE)  		return rb_move_tail(cpu_buffer, length, tail, -				    commit_page, tail_page, ts); +				    tail_page, ts);  	/* We reserved something on the buffer */ diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index 573d3cc762c..b2477caf09c 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -35,6 +35,28 @@ static int disable_reader;  module_param(disable_reader, uint, 0644);  MODULE_PARM_DESC(disable_reader, "only run producer"); +static int write_iteration = 50; +module_param(write_iteration, uint, 0644); +MODULE_PARM_DESC(write_iteration, "# of writes between timestamp readings"); + +static int producer_nice = 19; +static int consumer_nice = 19; + +static int producer_fifo = -1; +static int consumer_fifo = -1; + +module_param(producer_nice, uint, 0644); +MODULE_PARM_DESC(producer_nice, "nice prio for producer"); + +module_param(consumer_nice, uint, 0644); +MODULE_PARM_DESC(consumer_nice, "nice prio for consumer"); + +module_param(producer_fifo, uint, 0644); +MODULE_PARM_DESC(producer_fifo, "fifo prio for producer"); + +module_param(consumer_fifo, uint, 0644); +MODULE_PARM_DESC(consumer_fifo, "fifo prio for consumer"); +  static int read_events;  static int kill_test; @@ -208,15 +230,18 @@ static void ring_buffer_producer(void)  	do {  		struct ring_buffer_event *event;  		int *entry; +		int i; -		event = ring_buffer_lock_reserve(buffer, 10); -		if (!event) { -			missed++; -		} else { -			hit++; -			entry = ring_buffer_event_data(event); -			*entry = smp_processor_id(); -			ring_buffer_unlock_commit(buffer, event); +		for (i = 0; i < write_iteration; i++) { +			event = ring_buffer_lock_reserve(buffer, 10); +			if (!event) { +				missed++; +			} else { +				hit++; +				entry = ring_buffer_event_data(event); +				*entry = smp_processor_id(); +				ring_buffer_unlock_commit(buffer, event); +			}  		}  		do_gettimeofday(&end_tv); @@ -263,6 +288,27 @@ static void ring_buffer_producer(void)  	if (kill_test)  		trace_printk("ERROR!\n"); + +	if (!disable_reader) { +		if (consumer_fifo < 0) +			trace_printk("Running Consumer at nice: %d\n", +				     consumer_nice); +		else +			trace_printk("Running Consumer at SCHED_FIFO %d\n", +				     consumer_fifo); +	} +	if (producer_fifo < 0) +		trace_printk("Running Producer at nice: %d\n", +			     producer_nice); +	else +		trace_printk("Running Producer at SCHED_FIFO %d\n", +			     producer_fifo); + +	/* Let the user know that the test is running at low priority */ +	if (producer_fifo < 0 && consumer_fifo < 0 && +	    producer_nice == 19 && consumer_nice == 19) +		trace_printk("WARNING!!! This test is running at lowest priority.\n"); +  	trace_printk("Time:     %lld (usecs)\n", time);  	trace_printk("Overruns: %lld\n", overruns);  	if (disable_reader) @@ -392,6 +438,27 @@ static int __init ring_buffer_benchmark_init(void)  	if (IS_ERR(producer))  		goto out_kill; +	/* +	 * Run them as low-prio background tasks by default: +	 */ +	if (!disable_reader) { +		if (consumer_fifo >= 0) { +			struct sched_param param = { +				.sched_priority = consumer_fifo +			}; +			sched_setscheduler(consumer, SCHED_FIFO, ¶m); +		} else +			set_user_nice(consumer, consumer_nice); +	} + +	if (producer_fifo >= 0) { +		struct sched_param param = { +			.sched_priority = consumer_fifo +		}; +		sched_setscheduler(producer, SCHED_FIFO, ¶m); +	} else +		set_user_nice(producer, producer_nice); +  	return 0;   out_kill: diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b20d3ec75de..874f2893cff 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -129,7 +129,7 @@ static int tracing_set_tracer(const char *buf);  static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata;  static char *default_bootup_tracer; -static int __init set_ftrace(char *str) +static int __init set_cmdline_ftrace(char *str)  {  	strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);  	default_bootup_tracer = bootup_tracer_buf; @@ -137,7 +137,7 @@ static int __init set_ftrace(char *str)  	ring_buffer_expanded = 1;  	return 1;  } -__setup("ftrace=", set_ftrace); +__setup("ftrace=", set_cmdline_ftrace);  static int __init set_ftrace_dump_on_oops(char *str)  { @@ -1361,10 +1361,11 @@ int trace_array_vprintk(struct trace_array *tr,  	pause_graph_tracing();  	raw_local_irq_save(irq_flags);  	__raw_spin_lock(&trace_buf_lock); -	len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); - -	len = min(len, TRACE_BUF_SIZE-1); -	trace_buf[len] = 0; +	if (args == NULL) { +		strncpy(trace_buf, fmt, TRACE_BUF_SIZE); +		len = strlen(trace_buf); +	} else +		len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args);  	size = sizeof(*entry) + len + 1;  	buffer = tr->buffer; @@ -1373,10 +1374,10 @@ int trace_array_vprintk(struct trace_array *tr,  	if (!event)  		goto out_unlock;  	entry = ring_buffer_event_data(event); -	entry->ip			= ip; +	entry->ip = ip;  	memcpy(&entry->buf, trace_buf, len); -	entry->buf[len] = 0; +	entry->buf[len] = '\0';  	if (!filter_check_discard(call, entry, buffer, event))  		ring_buffer_unlock_commit(buffer, event); @@ -3319,22 +3320,11 @@ tracing_entries_write(struct file *filp, const char __user *ubuf,  	return cnt;  } -static int mark_printk(const char *fmt, ...) -{ -	int ret; -	va_list args; -	va_start(args, fmt); -	ret = trace_vprintk(0, fmt, args); -	va_end(args); -	return ret; -} -  static ssize_t  tracing_mark_write(struct file *filp, const char __user *ubuf,  					size_t cnt, loff_t *fpos)  {  	char *buf; -	char *end;  	if (tracing_disabled)  		return -EINVAL; @@ -3342,7 +3332,7 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,  	if (cnt > TRACE_BUF_SIZE)  		cnt = TRACE_BUF_SIZE; -	buf = kmalloc(cnt + 1, GFP_KERNEL); +	buf = kmalloc(cnt + 2, GFP_KERNEL);  	if (buf == NULL)  		return -ENOMEM; @@ -3350,14 +3340,13 @@ tracing_mark_write(struct file *filp, const char __user *ubuf,  		kfree(buf);  		return -EFAULT;  	} +	if (buf[cnt-1] != '\n') { +		buf[cnt] = '\n'; +		buf[cnt+1] = '\0'; +	} else +		buf[cnt] = '\0'; -	/* Cut from the first nil or newline. */ -	buf[cnt] = '\0'; -	end = strchr(buf, '\n'); -	if (end) -		*end = '\0'; - -	cnt = mark_printk("%s\n", buf); +	cnt = trace_vprintk(0, buf, NULL);  	kfree(buf);  	*fpos += cnt; @@ -3730,7 +3719,7 @@ tracing_stats_read(struct file *filp, char __user *ubuf,  	s = kmalloc(sizeof(*s), GFP_KERNEL);  	if (!s) -		return ENOMEM; +		return -ENOMEM;  	trace_seq_init(s); diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 405cb850b75..acef8b4636f 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -483,10 +483,6 @@ static inline int ftrace_graph_addr(unsigned long addr)  	return 0;  }  #else -static inline int ftrace_trace_addr(unsigned long addr) -{ -	return 1; -}  static inline int ftrace_graph_addr(unsigned long addr)  {  	return 1; @@ -500,12 +496,12 @@ print_graph_function(struct trace_iterator *iter)  }  #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -extern struct pid *ftrace_pid_trace; +extern struct list_head ftrace_pids;  #ifdef CONFIG_FUNCTION_TRACER  static inline int ftrace_trace_task(struct task_struct *task)  { -	if (!ftrace_pid_trace) +	if (list_empty(&ftrace_pids))  		return 1;  	return test_tsk_trace_trace(task); @@ -699,22 +695,40 @@ struct event_subsystem {  };  struct filter_pred; +struct regex;  typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,  				 int val1, int val2); +typedef int (*regex_match_func)(char *str, struct regex *r, int len); + +enum regex_type { +	MATCH_FULL, +	MATCH_FRONT_ONLY, +	MATCH_MIDDLE_ONLY, +	MATCH_END_ONLY, +}; + +struct regex { +	char			pattern[MAX_FILTER_STR_VAL]; +	int			len; +	int			field_len; +	regex_match_func	match; +}; +  struct filter_pred { -	filter_pred_fn_t fn; -	u64 val; -	char str_val[MAX_FILTER_STR_VAL]; -	int str_len; -	char *field_name; -	int offset; -	int not; -	int op; -	int pop_n; +	filter_pred_fn_t 	fn; +	u64 			val; +	struct regex		regex; +	char 			*field_name; +	int 			offset; +	int 			not; +	int 			op; +	int 			pop_n;  }; +extern enum regex_type +filter_parse_regex(char *buff, int len, char **search, int *not);  extern void print_event_filter(struct ftrace_event_call *call,  			       struct trace_seq *s);  extern int apply_event_filter(struct ftrace_event_call *call, diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c index 20c5f92e28a..878c03f386b 100644 --- a/kernel/trace/trace_clock.c +++ b/kernel/trace/trace_clock.c @@ -20,6 +20,8 @@  #include <linux/ktime.h>  #include <linux/trace_clock.h> +#include "trace.h" +  /*   * trace_clock_local(): the simplest and least coherent tracing clock.   * @@ -28,17 +30,17 @@   */  u64 notrace trace_clock_local(void)  { -	unsigned long flags;  	u64 clock; +	int resched;  	/*  	 * sched_clock() is an architecture implemented, fast, scalable,  	 * lockless clock. It is not guaranteed to be coherent across  	 * CPUs, nor across CPU idle events.  	 */ -	raw_local_irq_save(flags); +	resched = ftrace_preempt_disable();  	clock = sched_clock(); -	raw_local_irq_restore(flags); +	ftrace_preempt_enable(resched);  	return clock;  } diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index d128f65778e..5e9ffc33f6d 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -878,9 +878,9 @@ event_subsystem_dir(const char *name, struct dentry *d_events)  			   "'%s/filter' entry\n", name);  	} -	entry = trace_create_file("enable", 0644, system->entry, -				  (void *)system->name, -				  &ftrace_system_enable_fops); +	trace_create_file("enable", 0644, system->entry, +			  (void *)system->name, +			  &ftrace_system_enable_fops);  	return system->entry;  } @@ -892,7 +892,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,  		 const struct file_operations *filter,  		 const struct file_operations *format)  { -	struct dentry *entry;  	int ret;  	/* @@ -910,12 +909,12 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,  	}  	if (call->regfunc) -		entry = trace_create_file("enable", 0644, call->dir, call, -					  enable); +		trace_create_file("enable", 0644, call->dir, call, +				  enable);  	if (call->id && call->profile_enable) -		entry = trace_create_file("id", 0444, call->dir, call, -					  id); +		trace_create_file("id", 0444, call->dir, call, +		 		  id);  	if (call->define_fields) {  		ret = call->define_fields(call); @@ -924,16 +923,16 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events,  				   " events/%s\n", call->name);  			return ret;  		} -		entry = trace_create_file("filter", 0644, call->dir, call, -					  filter); +		trace_create_file("filter", 0644, call->dir, call, +				  filter);  	}  	/* A trace may not want to export its format */  	if (!call->show_format)  		return 0; -	entry = trace_create_file("format", 0444, call->dir, call, -				  format); +	trace_create_file("format", 0444, call->dir, call, +			  format);  	return 0;  } diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 98a6cc5c64e..92672016da2 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -18,8 +18,6 @@   * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>   */ -#include <linux/debugfs.h> -#include <linux/uaccess.h>  #include <linux/module.h>  #include <linux/ctype.h>  #include <linux/mutex.h> @@ -197,9 +195,9 @@ static int filter_pred_string(struct filter_pred *pred, void *event,  	char *addr = (char *)(event + pred->offset);  	int cmp, match; -	cmp = strncmp(addr, pred->str_val, pred->str_len); +	cmp = pred->regex.match(addr, &pred->regex, pred->regex.field_len); -	match = (!cmp) ^ pred->not; +	match = cmp ^ pred->not;  	return match;  } @@ -211,9 +209,9 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event,  	char **addr = (char **)(event + pred->offset);  	int cmp, match; -	cmp = strncmp(*addr, pred->str_val, pred->str_len); +	cmp = pred->regex.match(*addr, &pred->regex, pred->regex.field_len); -	match = (!cmp) ^ pred->not; +	match = cmp ^ pred->not;  	return match;  } @@ -237,9 +235,9 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event,  	char *addr = (char *)(event + str_loc);  	int cmp, match; -	cmp = strncmp(addr, pred->str_val, str_len); +	cmp = pred->regex.match(addr, &pred->regex, str_len); -	match = (!cmp) ^ pred->not; +	match = cmp ^ pred->not;  	return match;  } @@ -250,6 +248,124 @@ static int filter_pred_none(struct filter_pred *pred, void *event,  	return 0;  } +/* Basic regex callbacks */ +static int regex_match_full(char *str, struct regex *r, int len) +{ +	if (strncmp(str, r->pattern, len) == 0) +		return 1; +	return 0; +} + +static int regex_match_front(char *str, struct regex *r, int len) +{ +	if (strncmp(str, r->pattern, len) == 0) +		return 1; +	return 0; +} + +static int regex_match_middle(char *str, struct regex *r, int len) +{ +	if (strstr(str, r->pattern)) +		return 1; +	return 0; +} + +static int regex_match_end(char *str, struct regex *r, int len) +{ +	char *ptr = strstr(str, r->pattern); + +	if (ptr && (ptr[r->len] == 0)) +		return 1; +	return 0; +} + +/** + * filter_parse_regex - parse a basic regex + * @buff:   the raw regex + * @len:    length of the regex + * @search: will point to the beginning of the string to compare + * @not:    tell whether the match will have to be inverted + * + * This passes in a buffer containing a regex and this function will + * set search to point to the search part of the buffer and + * return the type of search it is (see enum above). + * This does modify buff. + * + * Returns enum type. + *  search returns the pointer to use for comparison. + *  not returns 1 if buff started with a '!' + *     0 otherwise. + */ +enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not) +{ +	int type = MATCH_FULL; +	int i; + +	if (buff[0] == '!') { +		*not = 1; +		buff++; +		len--; +	} else +		*not = 0; + +	*search = buff; + +	for (i = 0; i < len; i++) { +		if (buff[i] == '*') { +			if (!i) { +				*search = buff + 1; +				type = MATCH_END_ONLY; +			} else { +				if (type == MATCH_END_ONLY) +					type = MATCH_MIDDLE_ONLY; +				else +					type = MATCH_FRONT_ONLY; +				buff[i] = 0; +				break; +			} +		} +	} + +	return type; +} + +static int filter_build_regex(struct filter_pred *pred) +{ +	struct regex *r = &pred->regex; +	char *search, *dup; +	enum regex_type type; +	int not; + +	type = filter_parse_regex(r->pattern, r->len, &search, ¬); +	dup = kstrdup(search, GFP_KERNEL); +	if (!dup) +		return -ENOMEM; + +	strcpy(r->pattern, dup); +	kfree(dup); + +	r->len = strlen(r->pattern); + +	switch (type) { +	case MATCH_FULL: +		r->match = regex_match_full; +		break; +	case MATCH_FRONT_ONLY: +		r->match = regex_match_front; +		break; +	case MATCH_MIDDLE_ONLY: +		r->match = regex_match_middle; +		break; +	case MATCH_END_ONLY: +		r->match = regex_match_end; +		break; +	} + +	pred->not ^= not; + +	return 0; +} +  /* return 1 if event matches, 0 otherwise (discard) */  int filter_match_preds(struct ftrace_event_call *call, void *rec)  { @@ -396,7 +512,7 @@ static void filter_clear_pred(struct filter_pred *pred)  {  	kfree(pred->field_name);  	pred->field_name = NULL; -	pred->str_len = 0; +	pred->regex.len = 0;  }  static int filter_set_pred(struct filter_pred *dest, @@ -660,21 +776,24 @@ static int filter_add_pred(struct filter_parse_state *ps,  	}  	if (is_string_field(field)) { -		pred->str_len = field->size; +		ret = filter_build_regex(pred); +		if (ret) +			return ret; -		if (field->filter_type == FILTER_STATIC_STRING) +		if (field->filter_type == FILTER_STATIC_STRING) {  			fn = filter_pred_string; -		else if (field->filter_type == FILTER_DYN_STRING) -			fn = filter_pred_strloc; +			pred->regex.field_len = field->size; +		} else if (field->filter_type == FILTER_DYN_STRING) +				fn = filter_pred_strloc;  		else {  			fn = filter_pred_pchar; -			pred->str_len = strlen(pred->str_val); +			pred->regex.field_len = strlen(pred->regex.pattern);  		}  	} else {  		if (field->is_signed) -			ret = strict_strtoll(pred->str_val, 0, &val); +			ret = strict_strtoll(pred->regex.pattern, 0, &val);  		else -			ret = strict_strtoull(pred->str_val, 0, &val); +			ret = strict_strtoull(pred->regex.pattern, 0, &val);  		if (ret) {  			parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);  			return -EINVAL; @@ -1045,8 +1164,8 @@ static struct filter_pred *create_pred(int op, char *operand1, char *operand2)  		return NULL;  	} -	strcpy(pred->str_val, operand2); -	pred->str_len = strlen(operand2); +	strcpy(pred->regex.pattern, operand2); +	pred->regex.len = strlen(pred->regex.pattern);  	pred->op = op; diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c index 9753fcc61bc..c74848ddb85 100644 --- a/kernel/trace/trace_export.c +++ b/kernel/trace/trace_export.c @@ -48,11 +48,11 @@  struct ____ftrace_##name {					\  	tstruct							\  };								\ -static void __used ____ftrace_check_##name(void)		\ +static void __always_unused ____ftrace_check_##name(void)	\  {								\  	struct ____ftrace_##name *__entry = NULL;		\  								\ -	/* force cmpile-time check on F_printk() */		\ +	/* force compile-time check on F_printk() */		\  	printk(print);						\  } diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 527e17eae57..ddee9c59373 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -14,6 +14,69 @@ static int sys_refcount_exit;  static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);  static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); +extern unsigned long __start_syscalls_metadata[]; +extern unsigned long __stop_syscalls_metadata[]; + +static struct syscall_metadata **syscalls_metadata; + +static struct syscall_metadata *find_syscall_meta(unsigned long syscall) +{ +	struct syscall_metadata *start; +	struct syscall_metadata *stop; +	char str[KSYM_SYMBOL_LEN]; + + +	start = (struct syscall_metadata *)__start_syscalls_metadata; +	stop = (struct syscall_metadata *)__stop_syscalls_metadata; +	kallsyms_lookup(syscall, NULL, NULL, NULL, str); + +	for ( ; start < stop; start++) { +		/* +		 * Only compare after the "sys" prefix. Archs that use +		 * syscall wrappers may have syscalls symbols aliases prefixed +		 * with "SyS" instead of "sys", leading to an unwanted +		 * mismatch. +		 */ +		if (start->name && !strcmp(start->name + 3, str + 3)) +			return start; +	} +	return NULL; +} + +static struct syscall_metadata *syscall_nr_to_meta(int nr) +{ +	if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) +		return NULL; + +	return syscalls_metadata[nr]; +} + +int syscall_name_to_nr(char *name) +{ +	int i; + +	if (!syscalls_metadata) +		return -1; + +	for (i = 0; i < NR_syscalls; i++) { +		if (syscalls_metadata[i]) { +			if (!strcmp(syscalls_metadata[i]->name, name)) +				return i; +		} +	} +	return -1; +} + +void set_syscall_enter_id(int num, int id) +{ +	syscalls_metadata[num]->enter_id = id; +} + +void set_syscall_exit_id(int num, int id) +{ +	syscalls_metadata[num]->exit_id = id; +} +  enum print_line_t  print_syscall_enter(struct trace_iterator *iter, int flags)  { @@ -375,6 +438,29 @@ struct trace_event event_syscall_exit = {  	.trace			= print_syscall_exit,  }; +int __init init_ftrace_syscalls(void) +{ +	struct syscall_metadata *meta; +	unsigned long addr; +	int i; + +	syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * +					NR_syscalls, GFP_KERNEL); +	if (!syscalls_metadata) { +		WARN_ON(1); +		return -ENOMEM; +	} + +	for (i = 0; i < NR_syscalls; i++) { +		addr = arch_syscall_addr(i); +		meta = find_syscall_meta(addr); +		syscalls_metadata[i] = meta; +	} + +	return 0; +} +core_initcall(init_ftrace_syscalls); +  #ifdef CONFIG_EVENT_PROFILE  static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 234ceb10861..a79c4d0407a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -750,7 +750,7 @@ config RCU_TORTURE_TEST_RUNNABLE  config RCU_CPU_STALL_DETECTOR  	bool "Check for stalled CPUs delaying RCU grace periods"  	depends on TREE_RCU || TREE_PREEMPT_RCU -	default n +	default y  	help  	  This option causes RCU to printk information on which  	  CPUs are delaying the current grace period, but only when diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c index 39f1029e352..4ebfa5a164d 100644 --- a/lib/kernel_lock.c +++ b/lib/kernel_lock.c @@ -5,10 +5,13 @@   * relegated to obsolescence, but used by various less   * important (or lazy) subsystems.   */ -#include <linux/smp_lock.h>  #include <linux/module.h>  #include <linux/kallsyms.h>  #include <linux/semaphore.h> +#include <linux/smp_lock.h> + +#define CREATE_TRACE_POINTS +#include <trace/events/bkl.h>  /*   * The 'big kernel lock' @@ -113,21 +116,26 @@ static inline void __unlock_kernel(void)   * This cannot happen asynchronously, so we only need to   * worry about other CPU's.   */ -void __lockfunc lock_kernel(void) +void __lockfunc _lock_kernel(const char *func, const char *file, int line)  { -	int depth = current->lock_depth+1; +	int depth = current->lock_depth + 1; + +	trace_lock_kernel(func, file, line); +  	if (likely(!depth))  		__lock_kernel();  	current->lock_depth = depth;  } -void __lockfunc unlock_kernel(void) +void __lockfunc _unlock_kernel(const char *func, const char *file, int line)  {  	BUG_ON(current->lock_depth < 0);  	if (likely(--current->lock_depth < 0))  		__unlock_kernel(); + +	trace_unlock_kernel(func, file, line);  } -EXPORT_SYMBOL(lock_kernel); -EXPORT_SYMBOL(unlock_kernel); +EXPORT_SYMBOL(_lock_kernel); +EXPORT_SYMBOL(_unlock_kernel); diff --git a/lib/ratelimit.c b/lib/ratelimit.c index 26187edcc7e..09f5ce1810d 100644 --- a/lib/ratelimit.c +++ b/lib/ratelimit.c @@ -7,15 +7,12 @@   * parameter. Now every user can use their own standalone ratelimit_state.   *   * This file is released under the GPLv2. - *   */ -#include <linux/kernel.h> +#include <linux/ratelimit.h>  #include <linux/jiffies.h>  #include <linux/module.h> -static DEFINE_SPINLOCK(ratelimit_lock); -  /*   * __ratelimit - rate limiting   * @rs: ratelimit_state data @@ -23,35 +20,43 @@ static DEFINE_SPINLOCK(ratelimit_lock);   * This enforces a rate limit: not more than @rs->ratelimit_burst callbacks   * in every @rs->ratelimit_jiffies   */ -int __ratelimit(struct ratelimit_state *rs) +int ___ratelimit(struct ratelimit_state *rs, const char *func)  {  	unsigned long flags; +	int ret;  	if (!rs->interval)  		return 1; -	spin_lock_irqsave(&ratelimit_lock, flags); +	/* +	 * If we contend on this state's lock then almost +	 * by definition we are too busy to print a message, +	 * in addition to the one that will be printed by +	 * the entity that is holding the lock already: +	 */ +	if (!spin_trylock_irqsave(&rs->lock, flags)) +		return 1; +  	if (!rs->begin)  		rs->begin = jiffies;  	if (time_is_before_jiffies(rs->begin + rs->interval)) {  		if (rs->missed)  			printk(KERN_WARNING "%s: %d callbacks suppressed\n", -				__func__, rs->missed); -		rs->begin = 0; +				func, rs->missed); +		rs->begin   = 0;  		rs->printed = 0; -		rs->missed = 0; +		rs->missed  = 0;  	} -	if (rs->burst && rs->burst > rs->printed) -		goto print; - -	rs->missed++; -	spin_unlock_irqrestore(&ratelimit_lock, flags); -	return 0; +	if (rs->burst && rs->burst > rs->printed) { +		rs->printed++; +		ret = 1; +	} else { +		rs->missed++; +		ret = 0; +	} +	spin_unlock_irqrestore(&rs->lock, flags); -print: -	rs->printed++; -	spin_unlock_irqrestore(&ratelimit_lock, flags); -	return 1; +	return ret;  } -EXPORT_SYMBOL(__ratelimit); +EXPORT_SYMBOL(___ratelimit); diff --git a/lib/swiotlb.c b/lib/swiotlb.c index ac25cd28e80..795472d8ae2 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -97,6 +97,8 @@ static phys_addr_t *io_tlb_orig_addr;   */  static DEFINE_SPINLOCK(io_tlb_lock); +static int late_alloc; +  static int __init  setup_io_tlb_npages(char *str)  { @@ -109,6 +111,7 @@ setup_io_tlb_npages(char *str)  		++str;  	if (!strcmp(str, "force"))  		swiotlb_force = 1; +  	return 1;  }  __setup("swiotlb=", setup_io_tlb_npages); @@ -121,8 +124,9 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,  	return phys_to_dma(hwdev, virt_to_phys(address));  } -static void swiotlb_print_info(unsigned long bytes) +void swiotlb_print_info(void)  { +	unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;  	phys_addr_t pstart, pend;  	pstart = virt_to_phys(io_tlb_start); @@ -140,7 +144,7 @@ static void swiotlb_print_info(unsigned long bytes)   * structures for the software IO TLB used to implement the DMA API.   */  void __init -swiotlb_init_with_default_size(size_t default_size) +swiotlb_init_with_default_size(size_t default_size, int verbose)  {  	unsigned long i, bytes; @@ -176,14 +180,14 @@ swiotlb_init_with_default_size(size_t default_size)  	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);  	if (!io_tlb_overflow_buffer)  		panic("Cannot allocate SWIOTLB overflow buffer!\n"); - -	swiotlb_print_info(bytes); +	if (verbose) +		swiotlb_print_info();  }  void __init -swiotlb_init(void) +swiotlb_init(int verbose)  { -	swiotlb_init_with_default_size(64 * (1<<20));	/* default to 64MB */ +	swiotlb_init_with_default_size(64 * (1<<20), verbose);	/* default to 64MB */  }  /* @@ -260,7 +264,9 @@ swiotlb_late_init_with_default_size(size_t default_size)  	if (!io_tlb_overflow_buffer)  		goto cleanup4; -	swiotlb_print_info(bytes); +	swiotlb_print_info(); + +	late_alloc = 1;  	return 0; @@ -281,6 +287,32 @@ cleanup1:  	return -ENOMEM;  } +void __init swiotlb_free(void) +{ +	if (!io_tlb_overflow_buffer) +		return; + +	if (late_alloc) { +		free_pages((unsigned long)io_tlb_overflow_buffer, +			   get_order(io_tlb_overflow)); +		free_pages((unsigned long)io_tlb_orig_addr, +			   get_order(io_tlb_nslabs * sizeof(phys_addr_t))); +		free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * +								 sizeof(int))); +		free_pages((unsigned long)io_tlb_start, +			   get_order(io_tlb_nslabs << IO_TLB_SHIFT)); +	} else { +		free_bootmem_late(__pa(io_tlb_overflow_buffer), +				  io_tlb_overflow); +		free_bootmem_late(__pa(io_tlb_orig_addr), +				  io_tlb_nslabs * sizeof(phys_addr_t)); +		free_bootmem_late(__pa(io_tlb_list), +				  io_tlb_nslabs * sizeof(int)); +		free_bootmem_late(__pa(io_tlb_start), +				  io_tlb_nslabs << IO_TLB_SHIFT); +	} +} +  static int is_swiotlb_buffer(phys_addr_t paddr)  {  	return paddr >= virt_to_phys(io_tlb_start) && diff --git a/mm/bootmem.c b/mm/bootmem.c index 555d5d2731c..d1dc23cc7f1 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -143,6 +143,30 @@ unsigned long __init init_bootmem(unsigned long start, unsigned long pages)  	return init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages);  } +/* + * free_bootmem_late - free bootmem pages directly to page allocator + * @addr: starting address of the range + * @size: size of the range in bytes + * + * This is only useful when the bootmem allocator has already been torn + * down, but we are still initializing the system.  Pages are given directly + * to the page allocator, no bootmem metadata is updated because it is gone. + */ +void __init free_bootmem_late(unsigned long addr, unsigned long size) +{ +	unsigned long cursor, end; + +	kmemleak_free_part(__va(addr), size); + +	cursor = PFN_UP(addr); +	end = PFN_DOWN(addr + size); + +	for (; cursor < end; cursor++) { +		__free_pages_bootmem(pfn_to_page(cursor), 0); +		totalram_pages++; +	} +} +  static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)  {  	int aligned; diff --git a/mm/mmap.c b/mm/mmap.c index 73f5e4b6401..292ddc3cef9 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -20,7 +20,6 @@  #include <linux/fs.h>  #include <linux/personality.h>  #include <linux/security.h> -#include <linux/ima.h>  #include <linux/hugetlb.h>  #include <linux/profile.h>  #include <linux/module.h> @@ -1061,9 +1060,6 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,  	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);  	if (error)  		return error; -	error = ima_file_mmap(file, prot); -	if (error) -		return error;  	return mmap_region(file, addr, len, flags, vm_flags, pgoff);  } diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index fcfc5458c39..8938fa79124 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -10,7 +10,9 @@  #include <linux/module.h>  #include <linux/socket.h>  #include <linux/netdevice.h> +#include <linux/ratelimit.h>  #include <linux/init.h> +  #include <net/ip.h>  #include <net/sock.h> diff --git a/net/core/utils.c b/net/core/utils.c index 83221aee708..838250241d2 100644 --- a/net/core/utils.c +++ b/net/core/utils.c @@ -24,6 +24,8 @@  #include <linux/types.h>  #include <linux/percpu.h>  #include <linux/init.h> +#include <linux/ratelimit.h> +  #include <net/sock.h>  #include <asm/byteorder.h> diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 090d300d739..f0d14452632 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -6,77 +6,93 @@  #                   all the offsets to the calls to mcount.  #  # -# What we want to end up with is a section in vmlinux called -# __mcount_loc that contains a list of pointers to all the -# call sites in the kernel that call mcount. Later on boot up, the kernel -# will read this list, save the locations and turn them into nops. -# When tracing or profiling is later enabled, these locations will then -# be converted back to pointers to some function. +# What we want to end up with this is that each object file will have a +# section called __mcount_loc that will hold the list of pointers to mcount +# callers. After final linking, the vmlinux will have within .init.data the +# list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc. +# Later on boot up, the kernel will read this list, save the locations and turn +# them into nops. When tracing or profiling is later enabled, these locations +# will then be converted back to pointers to some function.  #  # This is no easy feat. This script is called just after the original  # object is compiled and before it is linked.  # -# The references to the call sites are offsets from the section of text -# that the call site is in. Hence, all functions in a section that -# has a call site to mcount, will have the offset from the beginning of -# the section and not the beginning of the function. +# When parse this object file using 'objdump', the references to the call +# sites are offsets from the section that the call site is in. Hence, all +# functions in a section that has a call site to mcount, will have the +# offset from the beginning of the section and not the beginning of the +# function. +# +# But where this section will reside finally in vmlinx is undetermined at +# this point. So we can't use this kind of offsets to record the final +# address of this call site. +# +# The trick is to change the call offset referring the start of a section to +# referring a function symbol in this section. During the link step, 'ld' will +# compute the final address according to the information we record.  # -# The trick is to find a way to record the beginning of the section. -# The way we do this is to look at the first function in the section -# which will also be the location of that section after final link.  # e.g.  #  #  .section ".sched.text", "ax" -#  .globl my_func -#  my_func:  #        [...] -#        call mcount  (offset: 0x5) +#  func1: +#        [...] +#        call mcount  (offset: 0x10)  #        [...]  #        ret -#  other_func: +#  .globl fun2 +#  func2:             (offset: 0x20)  #        [...] -#        call mcount (offset: 0x1b) +#        [...] +#        ret +#  func3: +#        [...] +#        call mcount (offset: 0x30)  #        [...]  #  # Both relocation offsets for the mcounts in the above example will be -# offset from .sched.text. If we make another file called tmp.s with: +# offset from .sched.text. If we choose global symbol func2 as a reference and +# make another file called tmp.s with the new offsets:  #  #  .section __mcount_loc -#  .quad  my_func + 0x5 -#  .quad  my_func + 0x1b +#  .quad  func2 - 0x10 +#  .quad  func2 + 0x10  # -# We can then compile this tmp.s into tmp.o, and link it to the original +# We can then compile this tmp.s into tmp.o, and link it back to the original  # object.  # -# But this gets hard if my_func is not globl (a static function). -# In such a case we have: +# In our algorithm, we will choose the first global function we meet in this +# section as the reference. But this gets hard if there is no global functions +# in this section. In such a case we have to select a local one. E.g. func1:  #  #  .section ".sched.text", "ax" -#  my_func: +#  func1:  #        [...] -#        call mcount  (offset: 0x5) +#        call mcount  (offset: 0x10)  #        [...]  #        ret -#  other_func: +#  func2:  #        [...] -#        call mcount (offset: 0x1b) +#        call mcount (offset: 0x20)  #        [...] +#  .section "other.section"  #  # If we make the tmp.s the same as above, when we link together with -# the original object, we will end up with two symbols for my_func: +# the original object, we will end up with two symbols for func1:  # one local, one global.  After final compile, we will end up with -# an undefined reference to my_func. +# an undefined reference to func1 or a wrong reference to another global +# func1 in other files.  #  # Since local objects can reference local variables, we need to find  # a way to make tmp.o reference the local objects of the original object -# file after it is linked together. To do this, we convert the my_func +# file after it is linked together. To do this, we convert func1  # into a global symbol before linking tmp.o. Then after we link tmp.o -# we will only have a single symbol for my_func that is global. -# We can convert my_func back into a local symbol and we are done. +# we will only have a single symbol for func1 that is global. +# We can convert func1 back into a local symbol and we are done.  #  # Here are the steps we take:  # -# 1) Record all the local symbols by using 'nm' +# 1) Record all the local and weak symbols by using 'nm'  # 2) Use objdump to find all the call site offsets and sections for  #    mcount.  # 3) Compile the list into its own object. @@ -86,10 +102,8 @@  # 6) Link together this new object with the list object.  # 7) Convert the local functions back to local symbols and rename  #    the result as the original object. -#    End.  # 8) Link the object with the list object.  # 9) Move the result back to the original object. -#    End.  #  use strict; @@ -99,7 +113,7 @@ $P =~ s@.*/@@g;  my $V = '0.1'; -if ($#ARGV < 7) { +if ($#ARGV != 10) {  	print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";  	print "version: $V\n";  	exit(1); @@ -109,7 +123,7 @@ my ($arch, $bits, $objdump, $objcopy, $cc,      $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;  # This file refers to mcount and shouldn't be ftraced, so lets' ignore it -if ($inputfile eq "kernel/trace/ftrace.o") { +if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {      exit(0);  } @@ -119,6 +133,7 @@ my %text_sections = (       ".sched.text" => 1,       ".spinlock.text" => 1,       ".irqentry.text" => 1, +     ".text.unlikely" => 1,  );  $objdump = "objdump" if ((length $objdump) == 0); @@ -137,13 +152,47 @@ my %weak;		# List of weak functions  my %convert;		# List of local functions used that needs conversion  my $type; -my $nm_regex;		# Find the local functions (return function) +my $local_regex;	# Match a local function (return function) +my $weak_regex; 	# Match a weak function (return function)  my $section_regex;	# Find the start of a section  my $function_regex;	# Find the name of a function  			#    (return offset and func name)  my $mcount_regex;	# Find the call site to mcount (return offset)  my $alignment;		# The .align value to use for $mcount_section  my $section_type;	# Section header plus possible alignment command +my $can_use_local = 0; 	# If we can use local function references + +# Shut up recordmcount if user has older objcopy +my $quiet_recordmcount = ".tmp_quiet_recordmcount"; +my $print_warning = 1; +$print_warning = 0 if ( -f $quiet_recordmcount); + +## +# check_objcopy - whether objcopy supports --globalize-symbols +# +#  --globalize-symbols came out in 2.17, we must test the version +#  of objcopy, and if it is less than 2.17, then we can not +#  record local functions. +sub check_objcopy +{ +    open (IN, "$objcopy --version |") or die "error running $objcopy"; +    while (<IN>) { +	if (/objcopy.*\s(\d+)\.(\d+)/) { +	    $can_use_local = 1 if ($1 > 2 || ($1 == 2 && $2 >= 17)); +	    last; +	} +    } +    close (IN); + +    if (!$can_use_local && $print_warning) { +	print STDERR "WARNING: could not find objcopy version or version " . +	    "is less than 2.17.\n" . +	    "\tLocal function references are disabled.\n"; +	open (QUIET, ">$quiet_recordmcount"); +	printf QUIET "Disables the warning from recordmcount.pl\n"; +	close QUIET; +    } +}  if ($arch eq "x86") {      if ($bits == 64) { @@ -157,7 +206,8 @@ if ($arch eq "x86") {  # We base the defaults off of i386, the other archs may  # feel free to change them in the below if statements.  # -$nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; +$local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; +$weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)";  $section_regex = "Disassembly of section\\s+(\\S+):";  $function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";  $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; @@ -206,7 +256,7 @@ if ($arch eq "x86_64") {      $cc .= " -m32";  } elsif ($arch eq "powerpc") { -    $nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; +    $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";      $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";      $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; @@ -278,44 +328,17 @@ if ($filename =~ m,^(.*)(\.\S),) {  my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";  my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o"; -# -# --globalize-symbols came out in 2.17, we must test the version -# of objcopy, and if it is less than 2.17, then we can not -# record local functions. -my $use_locals = 01; -my $local_warn_once = 0; -my $found_version = 0; - -open (IN, "$objcopy --version |") || die "error running $objcopy"; -while (<IN>) { -    if (/objcopy.*\s(\d+)\.(\d+)/) { -	my $major = $1; -	my $minor = $2; - -	$found_version = 1; -	if ($major < 2 || -	    ($major == 2 && $minor < 17)) { -	    $use_locals = 0; -	} -	last; -    } -} -close (IN); - -if (!$found_version) { -    print STDERR "WARNING: could not find objcopy version.\n" . -	"\tDisabling local function references.\n"; -} +check_objcopy();  #  # Step 1: find all the local (static functions) and weak symbols. -#        't' is local, 'w/W' is weak (we never use a weak function) +#         't' is local, 'w/W' is weak  #  open (IN, "$nm $inputfile|") || die "error running $nm";  while (<IN>) { -    if (/$nm_regex/) { +    if (/$local_regex/) {  	$locals{$1} = 1; -    } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) { +    } elsif (/$weak_regex/) {  	$weak{$2} = $1;      }  } @@ -333,26 +356,20 @@ my $offset = 0;		# offset of ref_func to section beginning  #  sub update_funcs  { -    return if ($#offsets < 0); +    return unless ($ref_func and @offsets); -    defined($ref_func) || die "No function to reference"; - -    # A section only had a weak function, to represent it. -    # Unfortunately, a weak function may be overwritten by another -    # function of the same name, making all these offsets incorrect. -    # To be safe, we simply print a warning and bail. +    # Sanity check on weak function. A weak function may be overwritten by +    # another function of the same name, making all these offsets incorrect.      if (defined $weak{$ref_func}) { -	print STDERR -	    "$inputfile: WARNING: referencing weak function" . +	die "$inputfile: ERROR: referencing weak function" .  	    " $ref_func for mcount\n"; -	return;      }      # is this function static? If so, note this fact.      if (defined $locals{$ref_func}) {  	# only use locals if objcopy supports globalize-symbols -	if (!$use_locals) { +	if (!$can_use_local) {  	    return;  	}  	$convert{$ref_func} = 1; @@ -378,9 +395,27 @@ open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump";  my $text; + +# read headers first  my $read_headers = 1;  while (<IN>) { + +    if ($read_headers && /$mcount_section/) { +	# +	# Somehow the make process can execute this script on an +	# object twice. If it does, we would duplicate the mcount +	# section and it will cause the function tracer self test +	# to fail. Check if the mcount section exists, and if it does, +	# warn and exit. +	# +	print STDERR "ERROR: $mcount_section already in $inputfile\n" . +	    "\tThis may be an indication that your build is corrupted.\n" . +	    "\tDelete $inputfile and try again. If the same object file\n" . +	    "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n"; +	exit(-1); +    } +      # is it a section?      if (/$section_regex/) {  	$read_headers = 0; @@ -392,7 +427,7 @@ while (<IN>) {  	    $read_function = 0;  	}  	# print out any recorded offsets -	update_funcs() if (defined($ref_func)); +	update_funcs();  	# reset all markers and arrays  	$text_found = 0; @@ -421,21 +456,7 @@ while (<IN>) {  		$offset = hex $1;  	    }  	} -    } elsif ($read_headers && /$mcount_section/) { -	# -	# Somehow the make process can execute this script on an -	# object twice. If it does, we would duplicate the mcount -	# section and it will cause the function tracer self test -	# to fail. Check if the mcount section exists, and if it does, -	# warn and exit. -	# -	print STDERR "ERROR: $mcount_section already in $inputfile\n" . -	    "\tThis may be an indication that your build is corrupted.\n" . -	    "\tDelete $inputfile and try again. If the same object file\n" . -	    "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n"; -	exit(-1);      } -      # is this a call site to mcount? If so, record it to print later      if ($text_found && /$mcount_regex/) {  	$offsets[$#offsets + 1] = hex $1; @@ -443,7 +464,7 @@ while (<IN>) {  }  # dump out anymore offsets that may have been found -update_funcs() if (defined($ref_func)); +update_funcs();  # If we did not find any mcount callers, we are done (do nothing).  if (!$opened) { diff --git a/scripts/selinux/Makefile b/scripts/selinux/Makefile index ca4b1ec0182..e8049da1831 100644 --- a/scripts/selinux/Makefile +++ b/scripts/selinux/Makefile @@ -1,2 +1,2 @@ -subdir-y := mdp -subdir-	+= mdp +subdir-y := mdp genheaders +subdir-	+= mdp genheaders diff --git a/scripts/selinux/genheaders/.gitignore b/scripts/selinux/genheaders/.gitignore new file mode 100644 index 00000000000..4c0b646ff8d --- /dev/null +++ b/scripts/selinux/genheaders/.gitignore @@ -0,0 +1 @@ +genheaders diff --git a/scripts/selinux/genheaders/Makefile b/scripts/selinux/genheaders/Makefile new file mode 100644 index 00000000000..417b165008e --- /dev/null +++ b/scripts/selinux/genheaders/Makefile @@ -0,0 +1,5 @@ +hostprogs-y	:= genheaders +HOST_EXTRACFLAGS += -Isecurity/selinux/include + +always		:= $(hostprogs-y) +clean-files	:= $(hostprogs-y) diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c new file mode 100644 index 00000000000..24626968055 --- /dev/null +++ b/scripts/selinux/genheaders/genheaders.c @@ -0,0 +1,118 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> + +struct security_class_mapping { +	const char *name; +	const char *perms[sizeof(unsigned) * 8 + 1]; +}; + +#include "classmap.h" +#include "initial_sid_to_string.h" + +#define max(x, y) (((int)(x) > (int)(y)) ? x : y) + +const char *progname; + +static void usage(void) +{ +	printf("usage: %s flask.h av_permissions.h\n", progname); +	exit(1); +} + +static char *stoupperx(const char *s) +{ +	char *s2 = strdup(s); +	char *p; + +	if (!s2) { +		fprintf(stderr, "%s:  out of memory\n", progname); +		exit(3); +	} + +	for (p = s2; *p; p++) +		*p = toupper(*p); +	return s2; +} + +int main(int argc, char *argv[]) +{ +	int i, j, k; +	int isids_len; +	FILE *fout; + +	progname = argv[0]; + +	if (argc < 3) +		usage(); + +	fout = fopen(argv[1], "w"); +	if (!fout) { +		fprintf(stderr, "Could not open %s for writing:  %s\n", +			argv[1], strerror(errno)); +		exit(2); +	} + +	for (i = 0; secclass_map[i].name; i++) { +		struct security_class_mapping *map = &secclass_map[i]; +		map->name = stoupperx(map->name); +		for (j = 0; map->perms[j]; j++) +			map->perms[j] = stoupperx(map->perms[j]); +	} + +	isids_len = sizeof(initial_sid_to_string) / sizeof (char *); +	for (i = 1; i < isids_len; i++) +		initial_sid_to_string[i] = stoupperx(initial_sid_to_string[i]); + +	fprintf(fout, "/* This file is automatically generated.  Do not edit. */\n"); +	fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n"); + +	for (i = 0; secclass_map[i].name; i++) { +		struct security_class_mapping *map = &secclass_map[i]; +		fprintf(fout, "#define SECCLASS_%s", map->name); +		for (j = 0; j < max(1, 40 - strlen(map->name)); j++) +			fprintf(fout, " "); +		fprintf(fout, "%2d\n", i+1); +	} + +	fprintf(fout, "\n"); + +	for (i = 1; i < isids_len; i++) { +		char *s = initial_sid_to_string[i]; +		fprintf(fout, "#define SECINITSID_%s", s); +		for (j = 0; j < max(1, 40 - strlen(s)); j++) +			fprintf(fout, " "); +		fprintf(fout, "%2d\n", i); +	} +	fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1); +	fprintf(fout, "\n#endif\n"); +	fclose(fout); + +	fout = fopen(argv[2], "w"); +	if (!fout) { +		fprintf(stderr, "Could not open %s for writing:  %s\n", +			argv[2], strerror(errno)); +		exit(4); +	} + +	fprintf(fout, "/* This file is automatically generated.  Do not edit. */\n"); +	fprintf(fout, "#ifndef _SELINUX_AV_PERMISSIONS_H_\n#define _SELINUX_AV_PERMISSIONS_H_\n\n"); + +	for (i = 0; secclass_map[i].name; i++) { +		struct security_class_mapping *map = &secclass_map[i]; +		for (j = 0; map->perms[j]; j++) { +			fprintf(fout, "#define %s__%s", map->name, +				map->perms[j]); +			for (k = 0; k < max(1, 40 - strlen(map->name) - strlen(map->perms[j])); k++) +				fprintf(fout, " "); +			fprintf(fout, "0x%08xUL\n", (1<<j)); +		} +	} + +	fprintf(fout, "\n#endif\n"); +	fclose(fout); +	exit(0); +} diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c index b4ced856258..62b34ce1f50 100644 --- a/scripts/selinux/mdp/mdp.c +++ b/scripts/selinux/mdp/mdp.c @@ -29,86 +29,27 @@  #include <unistd.h>  #include <string.h> -#include "flask.h" -  static void usage(char *name)  {  	printf("usage: %s [-m] policy_file context_file\n", name);  	exit(1);  } -static void find_common_name(char *cname, char *dest, int len) -{ -	char *start, *end; - -	start = strchr(cname, '_')+1; -	end = strchr(start, '_'); -	if (!start || !end || start-cname > len || end-start > len) { -		printf("Error with commons defines\n"); -		exit(1); -	} -	strncpy(dest, start, end-start); -	dest[end-start] = '\0'; -} - -#define S_(x) x, -static char *classlist[] = { -#include "class_to_string.h" -	NULL +/* Class/perm mapping support */ +struct security_class_mapping { +	const char *name; +	const char *perms[sizeof(unsigned) * 8 + 1];  }; -#undef S_ +#include "classmap.h"  #include "initial_sid_to_string.h" -#define TB_(x) char *x[] = { -#define TE_(x) NULL }; -#define S_(x) x, -#include "common_perm_to_string.h" -#undef TB_ -#undef TE_ -#undef S_ - -struct common { -	char *cname; -	char **perms; -}; -struct common common[] = { -#define TB_(x) { #x, x }, -#define S_(x) -#define TE_(x) -#include "common_perm_to_string.h" -#undef TB_ -#undef TE_ -#undef S_ -}; - -#define S_(x, y, z) {x, #y}, -struct av_inherit { -	int class; -	char *common; -}; -struct av_inherit av_inherit[] = { -#include "av_inherit.h" -}; -#undef S_ - -#include "av_permissions.h" -#define S_(x, y, z) {x, y, z}, -struct av_perms { -	int class; -	int perm_i; -	char *perm_s; -}; -struct av_perms av_perms[] = { -#include "av_perm_to_string.h" -}; -#undef S_ -  int main(int argc, char *argv[])  {  	int i, j, mls = 0; +	int initial_sid_to_string_len;  	char **arg, *polout, *ctxout; -	int classlist_len, initial_sid_to_string_len; +  	FILE *fout;  	if (argc < 3) @@ -127,64 +68,25 @@ int main(int argc, char *argv[])  		usage(argv[0]);  	} -	classlist_len = sizeof(classlist) / sizeof(char *);  	/* print out the classes */ -	for (i=1; i < classlist_len; i++) { -		if(classlist[i]) -			fprintf(fout, "class %s\n", classlist[i]); -		else -			fprintf(fout, "class user%d\n", i); -	} +	for (i = 0; secclass_map[i].name; i++) +		fprintf(fout, "class %s\n", secclass_map[i].name);  	fprintf(fout, "\n");  	initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);  	/* print out the sids */ -	for (i=1; i < initial_sid_to_string_len; i++) +	for (i = 1; i < initial_sid_to_string_len; i++)  		fprintf(fout, "sid %s\n", initial_sid_to_string[i]);  	fprintf(fout, "\n"); -	/* print out the commons */ -	for (i=0; i< sizeof(common)/sizeof(struct common); i++) { -		char cname[101]; -		find_common_name(common[i].cname, cname, 100); -		cname[100] = '\0'; -		fprintf(fout, "common %s\n{\n", cname); -		for (j=0; common[i].perms[j]; j++) -			fprintf(fout, "\t%s\n", common[i].perms[j]); -		fprintf(fout, "}\n\n"); -	} -	fprintf(fout, "\n"); -  	/* print out the class permissions */ -	for (i=1; i < classlist_len; i++) { -		if (classlist[i]) { -			int firstperm = -1, numperms = 0; - -			fprintf(fout, "class %s\n", classlist[i]); -			/* does it inherit from a common? */ -			for (j=0; j < sizeof(av_inherit)/sizeof(struct av_inherit); j++) -				if (av_inherit[j].class == i) -					fprintf(fout, "inherits %s\n", av_inherit[j].common); - -			for (j=0; j < sizeof(av_perms)/sizeof(struct av_perms); j++) { -				if (av_perms[j].class == i) { -					if (firstperm == -1) -						firstperm = j; -					numperms++; -				} -			} -			if (!numperms) { -				fprintf(fout, "\n"); -				continue; -			} - -			fprintf(fout, "{\n"); -			/* print out the av_perms */ -			for (j=0; j < numperms; j++) { -				fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s); -			} -			fprintf(fout, "}\n\n"); -		} +	for (i = 0; secclass_map[i].name; i++) { +		struct security_class_mapping *map = &secclass_map[i]; +		fprintf(fout, "class %s\n", map->name); +		fprintf(fout, "{\n"); +		for (j = 0; map->perms[j]; j++) +			fprintf(fout, "\t%s\n", map->perms[j]); +		fprintf(fout, "}\n\n");  	}  	fprintf(fout, "\n"); @@ -197,31 +99,34 @@ int main(int argc, char *argv[])  	/* types, roles, and allows */  	fprintf(fout, "type base_t;\n");  	fprintf(fout, "role base_r types { base_t };\n"); -	for (i=1; i < classlist_len; i++) { -		if (classlist[i]) -			fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]); -		else -			fprintf(fout, "allow base_t base_t:user%d *;\n", i); -	} +	for (i = 0; secclass_map[i].name; i++) +		fprintf(fout, "allow base_t base_t:%s *;\n", +			secclass_map[i].name);  	fprintf(fout, "user user_u roles { base_r };\n");  	fprintf(fout, "\n");  	/* default sids */ -	for (i=1; i < initial_sid_to_string_len; i++) +	for (i = 1; i < initial_sid_to_string_len; i++)  		fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);  	fprintf(fout, "\n"); -  	fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_xattr lustre user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n"); +	fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n");  	fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n"); diff --git a/security/Kconfig b/security/Kconfig index fb363cd81cf..226b9556b25 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -91,28 +91,6 @@ config SECURITY_PATH  	  implement pathname based access controls.  	  If you are unsure how to answer this question, answer N. -config SECURITY_FILE_CAPABILITIES -	bool "File POSIX Capabilities" -	default n -	help -	  This enables filesystem capabilities, allowing you to give -	  binaries a subset of root's powers without using setuid 0. - -	  If in doubt, answer N. - -config SECURITY_ROOTPLUG -	bool "Root Plug Support" -	depends on USB=y && SECURITY -	help -	  This is a sample LSM module that should only be used as such. -	  It prevents any programs running with egid == 0 if a specific -	  USB device is not present in the system. - -	  See <http://www.linuxjournal.com/article.php?sid=6279> for -	  more information about this module. - -	  If you are unsure how to answer this question, answer N. -  config INTEL_TXT  	bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"  	depends on HAVE_INTEL_TXT @@ -165,5 +143,37 @@ source security/tomoyo/Kconfig  source security/integrity/ima/Kconfig +choice +	prompt "Default security module" +	default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX +	default DEFAULT_SECURITY_SMACK if SECURITY_SMACK +	default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO +	default DEFAULT_SECURITY_DAC + +	help +	  Select the security module that will be used by default if the +	  kernel parameter security= is not specified. + +	config DEFAULT_SECURITY_SELINUX +		bool "SELinux" if SECURITY_SELINUX=y + +	config DEFAULT_SECURITY_SMACK +		bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y + +	config DEFAULT_SECURITY_TOMOYO +		bool "TOMOYO" if SECURITY_TOMOYO=y + +	config DEFAULT_SECURITY_DAC +		bool "Unix Discretionary Access Controls" + +endchoice + +config DEFAULT_SECURITY +	string +	default "selinux" if DEFAULT_SECURITY_SELINUX +	default "smack" if DEFAULT_SECURITY_SMACK +	default "tomoyo" if DEFAULT_SECURITY_TOMOYO +	default "" if DEFAULT_SECURITY_DAC +  endmenu diff --git a/security/Makefile b/security/Makefile index 95ecc06392d..bb44e350c61 100644 --- a/security/Makefile +++ b/security/Makefile @@ -18,7 +18,6 @@ obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o  obj-$(CONFIG_SECURITY_SMACK)		+= smack/built-in.o  obj-$(CONFIG_AUDIT)			+= lsm_audit.o  obj-$(CONFIG_SECURITY_TOMOYO)		+= tomoyo/built-in.o -obj-$(CONFIG_SECURITY_ROOTPLUG)		+= root_plug.o  obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o  # Object integrity file lists diff --git a/security/capability.c b/security/capability.c index fce07a7bc82..5c700e1a4fd 100644 --- a/security/capability.c +++ b/security/capability.c @@ -308,6 +308,22 @@ static int cap_path_truncate(struct path *path, loff_t length,  {  	return 0;  } + +static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt, +			  mode_t mode) +{ +	return 0; +} + +static int cap_path_chown(struct path *path, uid_t uid, gid_t gid) +{ +	return 0; +} + +static int cap_path_chroot(struct path *root) +{ +	return 0; +}  #endif  static int cap_file_permission(struct file *file, int mask) @@ -405,7 +421,7 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode)  	return 0;  } -static int cap_kernel_module_request(void) +static int cap_kernel_module_request(char *kmod_name)  {  	return 0;  } @@ -977,6 +993,9 @@ void security_fixup_ops(struct security_operations *ops)  	set_to_cap_if_null(ops, path_link);  	set_to_cap_if_null(ops, path_rename);  	set_to_cap_if_null(ops, path_truncate); +	set_to_cap_if_null(ops, path_chmod); +	set_to_cap_if_null(ops, path_chown); +	set_to_cap_if_null(ops, path_chroot);  #endif  	set_to_cap_if_null(ops, file_permission);  	set_to_cap_if_null(ops, file_alloc_security); diff --git a/security/commoncap.c b/security/commoncap.c index fe30751a6cd..f800fdb3de9 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -1,4 +1,4 @@ -/* Common capabilities, needed by capability.o and root_plug.o +/* Common capabilities, needed by capability.o.   *   *	This program is free software; you can redistribute it and/or modify   *	it under the terms of the GNU General Public License as published by @@ -173,7 +173,6 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective,   */  static inline int cap_inh_is_capped(void)  { -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  	/* they are so limited unless the current task has the CAP_SETPCAP  	 * capability @@ -181,7 +180,6 @@ static inline int cap_inh_is_capped(void)  	if (cap_capable(current, current_cred(), CAP_SETPCAP,  			SECURITY_CAP_AUDIT) == 0)  		return 0; -#endif  	return 1;  } @@ -239,8 +237,6 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm)  	bprm->cap_effective = false;  } -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES -  /**   * cap_inode_need_killpriv - Determine if inode change affects privileges   * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV @@ -421,49 +417,6 @@ out:  	return rc;  } -#else -int cap_inode_need_killpriv(struct dentry *dentry) -{ -	return 0; -} - -int cap_inode_killpriv(struct dentry *dentry) -{ -	return 0; -} - -int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) -{ -	memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); - 	return -ENODATA; -} - -static inline int get_file_caps(struct linux_binprm *bprm, bool *effective) -{ -	bprm_clear_caps(bprm); -	return 0; -} -#endif - -/* - * Determine whether a exec'ing process's new permitted capabilities should be - * limited to just what it already has. - * - * This prevents processes that are being ptraced from gaining access to - * CAP_SETPCAP, unless the process they're tracing already has it, and the - * binary they're executing has filecaps that elevate it. - * - *  Returns 1 if they should be limited, 0 if they are not. - */ -static inline int cap_limit_ptraced_target(void) -{ -#ifndef CONFIG_SECURITY_FILE_CAPABILITIES -	if (capable(CAP_SETPCAP)) -		return 0; -#endif -	return 1; -} -  /**   * cap_bprm_set_creds - Set up the proposed credentials for execve().   * @bprm: The execution parameters, including the proposed creds @@ -523,9 +476,8 @@ skip:  			new->euid = new->uid;  			new->egid = new->gid;  		} -		if (cap_limit_ptraced_target()) -			new->cap_permitted = cap_intersect(new->cap_permitted, -							   old->cap_permitted); +		new->cap_permitted = cap_intersect(new->cap_permitted, +						   old->cap_permitted);  	}  	new->suid = new->fsuid = new->euid; @@ -739,7 +691,6 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags)  	return 0;  } -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  /*   * Rationale: code calling task_setscheduler, task_setioprio, and   * task_setnice, assumes that @@ -820,22 +771,6 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap)  	return 0;  } -#else -int cap_task_setscheduler (struct task_struct *p, int policy, -			   struct sched_param *lp) -{ -	return 0; -} -int cap_task_setioprio (struct task_struct *p, int ioprio) -{ -	return 0; -} -int cap_task_setnice (struct task_struct *p, int nice) -{ -	return 0; -} -#endif -  /**   * cap_task_prctl - Implement process control functions for this security module   * @option: The process control function requested @@ -866,7 +801,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,  		error = !!cap_raised(new->cap_bset, arg2);  		goto no_change; -#ifdef CONFIG_SECURITY_FILE_CAPABILITIES  	case PR_CAPBSET_DROP:  		error = cap_prctl_drop(new, arg2);  		if (error < 0) @@ -917,8 +851,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,  		error = new->securebits;  		goto no_change; -#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ -  	case PR_GET_KEEPCAPS:  		if (issecure(SECURE_KEEP_CAPS))  			error = 1; diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 53d9764e8f0..3d7846de806 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -3,6 +3,7 @@  config IMA  	bool "Integrity Measurement Architecture(IMA)"  	depends on ACPI +	depends on SECURITY  	select SECURITYFS  	select CRYPTO  	select CRYPTO_HMAC diff --git a/security/lsm_audit.c b/security/lsm_audit.c index e04566a2c4e..acba3dfc8d2 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c @@ -354,6 +354,10 @@ static void dump_common_audit_data(struct audit_buffer *ab,  		}  		break;  #endif +	case LSM_AUDIT_DATA_KMOD: +		audit_log_format(ab, " kmod="); +		audit_log_untrustedstring(ab, a->u.kmod_name); +		break;  	} /* switch (a->type) */  } diff --git a/security/min_addr.c b/security/min_addr.c index c844eed7915..fc43c9d3708 100644 --- a/security/min_addr.c +++ b/security/min_addr.c @@ -33,6 +33,9 @@ int mmap_min_addr_handler(struct ctl_table *table, int write,  {  	int ret; +	if (!capable(CAP_SYS_RAWIO)) +		return -EPERM; +  	ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos);  	update_mmap_min_addr(); diff --git a/security/root_plug.c b/security/root_plug.c deleted file mode 100644 index 2f7ffa67c4d..00000000000 --- a/security/root_plug.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Root Plug sample LSM module - * - * Originally written for a Linux Journal. - * - * Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com> - * - * Prevents any programs running with egid == 0 if a specific USB device - * is not present in the system.  Yes, it can be gotten around, but is a - * nice starting point for people to play with, and learn the LSM - * interface. - * - * If you want to turn this into something with a semblance of security, - * you need to hook the task_* functions also. - * - * See http://www.linuxjournal.com/article.php?sid=6279 for more information - * about this code. - * - *	This program is free software; you can redistribute it and/or - *	modify it under the terms of the GNU General Public License as - *	published by the Free Software Foundation, version 2 of the - *	License. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/security.h> -#include <linux/usb.h> -#include <linux/moduleparam.h> - -/* default is a generic type of usb to serial converter */ -static int vendor_id = 0x0557; -static int product_id = 0x2008; - -module_param(vendor_id, uint, 0400); -module_param(product_id, uint, 0400); - -/* should we print out debug messages */ -static int debug = 0; - -module_param(debug, bool, 0600); - -#define MY_NAME "root_plug" - -#define root_dbg(fmt, arg...)					\ -	do {							\ -		if (debug)					\ -			printk(KERN_DEBUG "%s: %s: " fmt ,	\ -				MY_NAME , __func__ , 	\ -				## arg);			\ -	} while (0) - -static int rootplug_bprm_check_security (struct linux_binprm *bprm) -{ -	struct usb_device *dev; - -	root_dbg("file %s, e_uid = %d, e_gid = %d\n", -		 bprm->filename, bprm->cred->euid, bprm->cred->egid); - -	if (bprm->cred->egid == 0) { -		dev = usb_find_device(vendor_id, product_id); -		if (!dev) { -			root_dbg("e_gid = 0, and device not found, " -				 "task not allowed to run...\n"); -			return -EPERM; -		} -		usb_put_dev(dev); -	} - -	return 0; -} - -static struct security_operations rootplug_security_ops = { -	.bprm_check_security =		rootplug_bprm_check_security, -}; - -static int __init rootplug_init (void) -{ -	/* register ourselves with the security framework */ -	if (register_security (&rootplug_security_ops)) { -		printk (KERN_INFO  -			"Failure registering Root Plug module with the kernel\n"); -			return -EINVAL; -	} -	printk (KERN_INFO "Root Plug module initialized, " -		"vendor_id = %4.4x, product id = %4.4x\n", vendor_id, product_id); -	return 0; -} - -security_initcall (rootplug_init); diff --git a/security/security.c b/security/security.c index c4c673240c1..24e060be9fa 100644 --- a/security/security.c +++ b/security/security.c @@ -16,9 +16,11 @@  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/security.h> +#include <linux/ima.h>  /* Boot-time LSM user choice */ -static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1]; +static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = +	CONFIG_DEFAULT_SECURITY;  /* things that live in capability.c */  extern struct security_operations default_security_ops; @@ -79,8 +81,10 @@ __setup("security=", choose_lsm);   *   * Return true if:   *	-The passed LSM is the one chosen by user at boot time, - *	-or user didn't specify a specific LSM and we're the first to ask - *	 for registration permission, + *	-or the passed LSM is configured as the default and the user did not + *	 choose an alternate LSM at boot time, + *	-or there is no default LSM set and the user didn't specify a + *	 specific LSM and we're the first to ask for registration permission,   *	-or the passed LSM is currently loaded.   * Otherwise, return false.   */ @@ -235,7 +239,12 @@ int security_bprm_set_creds(struct linux_binprm *bprm)  int security_bprm_check(struct linux_binprm *bprm)  { -	return security_ops->bprm_check_security(bprm); +	int ret; + +	ret = security_ops->bprm_check_security(bprm); +	if (ret) +		return ret; +	return ima_bprm_check(bprm);  }  void security_bprm_committing_creds(struct linux_binprm *bprm) @@ -352,12 +361,21 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);  int security_inode_alloc(struct inode *inode)  { +	int ret; +  	inode->i_security = NULL; -	return security_ops->inode_alloc_security(inode); +	ret =  security_ops->inode_alloc_security(inode); +	if (ret) +		return ret; +	ret = ima_inode_alloc(inode); +	if (ret) +		security_inode_free(inode); +	return ret;  }  void security_inode_free(struct inode *inode)  { +	ima_inode_free(inode);  	security_ops->inode_free_security(inode);  } @@ -434,6 +452,26 @@ int security_path_truncate(struct path *path, loff_t length,  		return 0;  	return security_ops->path_truncate(path, length, time_attrs);  } + +int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, +			mode_t mode) +{ +	if (unlikely(IS_PRIVATE(dentry->d_inode))) +		return 0; +	return security_ops->path_chmod(dentry, mnt, mode); +} + +int security_path_chown(struct path *path, uid_t uid, gid_t gid) +{ +	if (unlikely(IS_PRIVATE(path->dentry->d_inode))) +		return 0; +	return security_ops->path_chown(path, uid, gid); +} + +int security_path_chroot(struct path *path) +{ +	return security_ops->path_chroot(path); +}  #endif  int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) @@ -628,6 +666,8 @@ int security_file_alloc(struct file *file)  void security_file_free(struct file *file)  {  	security_ops->file_free_security(file); +	if (file->f_dentry) +		ima_file_free(file);  }  int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -639,7 +679,12 @@ int security_file_mmap(struct file *file, unsigned long reqprot,  			unsigned long prot, unsigned long flags,  			unsigned long addr, unsigned long addr_only)  { -	return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); +	int ret; + +	ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); +	if (ret) +		return ret; +	return ima_file_mmap(file, prot);  }  int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, @@ -719,9 +764,9 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode)  	return security_ops->kernel_create_files_as(new, inode);  } -int security_kernel_module_request(void) +int security_kernel_module_request(char *kmod_name)  { -	return security_ops->kernel_module_request(); +	return security_ops->kernel_module_request(kmod_name);  }  int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) diff --git a/security/selinux/.gitignore b/security/selinux/.gitignore new file mode 100644 index 00000000000..2e5040a3d48 --- /dev/null +++ b/security/selinux/.gitignore @@ -0,0 +1,2 @@ +av_permissions.h +flask.h diff --git a/security/selinux/Makefile b/security/selinux/Makefile index d47fc5e545e..f013982df41 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -18,5 +18,13 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o  selinux-$(CONFIG_NETLABEL) += netlabel.o -EXTRA_CFLAGS += -Isecurity/selinux/include +EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include +$(obj)/avc.o: $(obj)/flask.h + +quiet_cmd_flask = GEN     $(obj)/flask.h $(obj)/av_permissions.h +      cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h + +targets += flask.h +$(obj)/flask.h: $(src)/include/classmap.h FORCE +	$(call if_changed,flask) diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b4b5da1c0a4..f2dde268165 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -31,43 +31,7 @@  #include <net/ipv6.h>  #include "avc.h"  #include "avc_ss.h" - -static const struct av_perm_to_string av_perm_to_string[] = { -#define S_(c, v, s) { c, v, s }, -#include "av_perm_to_string.h" -#undef S_ -}; - -static const char *class_to_string[] = { -#define S_(s) s, -#include "class_to_string.h" -#undef S_ -}; - -#define TB_(s) static const char *s[] = { -#define TE_(s) }; -#define S_(s) s, -#include "common_perm_to_string.h" -#undef TB_ -#undef TE_ -#undef S_ - -static const struct av_inherit av_inherit[] = { -#define S_(c, i, b) {	.tclass = c,\ -			.common_pts = common_##i##_perm_to_string,\ -			.common_base =  b }, -#include "av_inherit.h" -#undef S_ -}; - -const struct selinux_class_perm selinux_class_perm = { -	.av_perm_to_string = av_perm_to_string, -	.av_pts_len = ARRAY_SIZE(av_perm_to_string), -	.class_to_string = class_to_string, -	.cts_len = ARRAY_SIZE(class_to_string), -	.av_inherit = av_inherit, -	.av_inherit_len = ARRAY_SIZE(av_inherit) -}; +#include "classmap.h"  #define AVC_CACHE_SLOTS			512  #define AVC_DEF_CACHE_THRESHOLD		512 @@ -139,52 +103,28 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)   */  static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)  { -	const char **common_pts = NULL; -	u32 common_base = 0; -	int i, i2, perm; +	const char **perms; +	int i, perm;  	if (av == 0) {  		audit_log_format(ab, " null");  		return;  	} -	for (i = 0; i < ARRAY_SIZE(av_inherit); i++) { -		if (av_inherit[i].tclass == tclass) { -			common_pts = av_inherit[i].common_pts; -			common_base = av_inherit[i].common_base; -			break; -		} -	} +	perms = secclass_map[tclass-1].perms;  	audit_log_format(ab, " {");  	i = 0;  	perm = 1; -	while (perm < common_base) { -		if (perm & av) { -			audit_log_format(ab, " %s", common_pts[i]); +	while (i < (sizeof(av) * 8)) { +		if ((perm & av) && perms[i]) { +			audit_log_format(ab, " %s", perms[i]);  			av &= ~perm;  		}  		i++;  		perm <<= 1;  	} -	while (i < sizeof(av) * 8) { -		if (perm & av) { -			for (i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++) { -				if ((av_perm_to_string[i2].tclass == tclass) && -				    (av_perm_to_string[i2].value == perm)) -					break; -			} -			if (i2 < ARRAY_SIZE(av_perm_to_string)) { -				audit_log_format(ab, " %s", -						 av_perm_to_string[i2].name); -				av &= ~perm; -			} -		} -		i++; -		perm <<= 1; -	} -  	if (av)  		audit_log_format(ab, " 0x%x", av); @@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla  		kfree(scontext);  	} -	BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]); -	audit_log_format(ab, " tclass=%s", class_to_string[tclass]); +	BUG_ON(tclass >= ARRAY_SIZE(secclass_map)); +	audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);  }  /** diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 83a4aada0b4..7a374c2eb04 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -91,7 +91,6 @@  #define NUM_SEL_MNT_OPTS 5 -extern unsigned int policydb_loaded_version;  extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);  extern struct security_operations *security_ops; @@ -3338,9 +3337,18 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)  	return 0;  } -static int selinux_kernel_module_request(void) +static int selinux_kernel_module_request(char *kmod_name)  { -	return task_has_system(current, SYSTEM__MODULE_REQUEST); +	u32 sid; +	struct common_audit_data ad; + +	sid = task_sid(current); + +	COMMON_AUDIT_DATA_INIT(&ad, KMOD); +	ad.u.kmod_name = kmod_name; + +	return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, +			    SYSTEM__MODULE_REQUEST, &ad);  }  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) @@ -4714,10 +4722,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)  	if (err)  		return err; -	if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) -		err = selinux_nlmsg_perm(sk, skb); - -	return err; +	return selinux_nlmsg_perm(sk, skb);  }  static int selinux_netlink_recv(struct sk_buff *skb, int capability) @@ -5830,12 +5835,12 @@ int selinux_disable(void)  	selinux_disabled = 1;  	selinux_enabled = 0; -	/* Try to destroy the avc node cache */ -	avc_disable(); -  	/* Reset security_ops to the secondary module, dummy or capability. */  	security_ops = secondary_ops; +	/* Try to destroy the avc node cache */ +	avc_disable(); +  	/* Unregister netfilter hooks. */  	selinux_nf_ip_exit(); diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h deleted file mode 100644 index abedcd704da..00000000000 --- a/security/selinux/include/av_inherit.h +++ /dev/null @@ -1,34 +0,0 @@ -/* This file is automatically generated.  Do not edit. */ -   S_(SECCLASS_DIR, file, 0x00020000UL) -   S_(SECCLASS_FILE, file, 0x00020000UL) -   S_(SECCLASS_LNK_FILE, file, 0x00020000UL) -   S_(SECCLASS_CHR_FILE, file, 0x00020000UL) -   S_(SECCLASS_BLK_FILE, file, 0x00020000UL) -   S_(SECCLASS_SOCK_FILE, file, 0x00020000UL) -   S_(SECCLASS_FIFO_FILE, file, 0x00020000UL) -   S_(SECCLASS_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_TCP_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_UDP_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_RAWIP_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_PACKET_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_TUN_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_IPC, ipc, 0x00000200UL) -   S_(SECCLASS_SEM, ipc, 0x00000200UL) -   S_(SECCLASS_MSGQ, ipc, 0x00000200UL) -   S_(SECCLASS_SHM, ipc, 0x00000200UL) -   S_(SECCLASS_NETLINK_ROUTE_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_FIREWALL_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_NFLOG_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_XFRM_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_SELINUX_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_AUDIT_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) -   S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL) diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h deleted file mode 100644 index 2b683ad83d2..00000000000 --- a/security/selinux/include/av_perm_to_string.h +++ /dev/null @@ -1,183 +0,0 @@ -/* This file is automatically generated.  Do not edit. */ -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod") -   S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget") -   S_(SECCLASS_DIR, DIR__ADD_NAME, "add_name") -   S_(SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name") -   S_(SECCLASS_DIR, DIR__REPARENT, "reparent") -   S_(SECCLASS_DIR, DIR__SEARCH, "search") -   S_(SECCLASS_DIR, DIR__RMDIR, "rmdir") -   S_(SECCLASS_DIR, DIR__OPEN, "open") -   S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans") -   S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") -   S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") -   S_(SECCLASS_FILE, FILE__OPEN, "open") -   S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") -   S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint") -   S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") -   S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open") -   S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open") -   S_(SECCLASS_SOCK_FILE, SOCK_FILE__OPEN, "open") -   S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open") -   S_(SECCLASS_FD, FD__USE, "use") -   S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") -   S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn") -   S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom") -   S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind") -   S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NAME_CONNECT, "name_connect") -   S_(SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind") -   S_(SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind") -   S_(SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv") -   S_(SECCLASS_NODE, NODE__TCP_SEND, "tcp_send") -   S_(SECCLASS_NODE, NODE__UDP_RECV, "udp_recv") -   S_(SECCLASS_NODE, NODE__UDP_SEND, "udp_send") -   S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") -   S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") -   S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") -   S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") -   S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") -   S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom") -   S_(SECCLASS_NODE, NODE__SENDTO, "sendto") -   S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") -   S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") -   S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") -   S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") -   S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") -   S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") -   S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") -   S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") -   S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress") -   S_(SECCLASS_NETIF, NETIF__EGRESS, "egress") -   S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") -   S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") -   S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") -   S_(SECCLASS_PROCESS, PROCESS__FORK, "fork") -   S_(SECCLASS_PROCESS, PROCESS__TRANSITION, "transition") -   S_(SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld") -   S_(SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill") -   S_(SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop") -   S_(SECCLASS_PROCESS, PROCESS__SIGNULL, "signull") -   S_(SECCLASS_PROCESS, PROCESS__SIGNAL, "signal") -   S_(SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace") -   S_(SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched") -   S_(SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched") -   S_(SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession") -   S_(SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid") -   S_(SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid") -   S_(SECCLASS_PROCESS, PROCESS__GETCAP, "getcap") -   S_(SECCLASS_PROCESS, PROCESS__SETCAP, "setcap") -   S_(SECCLASS_PROCESS, PROCESS__SHARE, "share") -   S_(SECCLASS_PROCESS, PROCESS__GETATTR, "getattr") -   S_(SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec") -   S_(SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate") -   S_(SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure") -   S_(SECCLASS_PROCESS, PROCESS__SIGINH, "siginh") -   S_(SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit") -   S_(SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh") -   S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition") -   S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent") -   S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") -   S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") -   S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") -   S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") -   S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") -   S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") -   S_(SECCLASS_MSG, MSG__SEND, "send") -   S_(SECCLASS_MSG, MSG__RECEIVE, "receive") -   S_(SECCLASS_SHM, SHM__LOCK, "lock") -   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av") -   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create") -   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member") -   S_(SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context") -   S_(SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy") -   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel") -   S_(SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user") -   S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce") -   S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool") -   S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam") -   S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot") -   S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info") -   S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") -   S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") -   S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") -   S_(SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, "module_request") -   S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") -   S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") -   S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") -   S_(SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner") -   S_(SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid") -   S_(SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap") -   S_(SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable") -   S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service") -   S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast") -   S_(SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin") -   S_(SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw") -   S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock") -   S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config") -   S_(SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod") -   S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease") -   S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_WRITE, "audit_write") -   S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_CONTROL, "audit_control") -   S_(SECCLASS_CAPABILITY, CAPABILITY__SETFCAP, "setfcap") -   S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_OVERRIDE, "mac_override") -   S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_ADMIN, "mac_admin") -   S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read") -   S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write") -   S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read") -   S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write") -   S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read") -   S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write") -   S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read") -   S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write") -   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read") -   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write") -   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay") -   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv") -   S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT, "nlmsg_tty_audit") -   S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read") -   S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write") -   S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") -   S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") -   S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") -   S_(SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, "polmatch") -   S_(SECCLASS_PACKET, PACKET__SEND, "send") -   S_(SECCLASS_PACKET, PACKET__RECV, "recv") -   S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") -   S_(SECCLASS_PACKET, PACKET__FLOW_IN, "flow_in") -   S_(SECCLASS_PACKET, PACKET__FLOW_OUT, "flow_out") -   S_(SECCLASS_PACKET, PACKET__FORWARD_IN, "forward_in") -   S_(SECCLASS_PACKET, PACKET__FORWARD_OUT, "forward_out") -   S_(SECCLASS_KEY, KEY__VIEW, "view") -   S_(SECCLASS_KEY, KEY__READ, "read") -   S_(SECCLASS_KEY, KEY__WRITE, "write") -   S_(SECCLASS_KEY, KEY__SEARCH, "search") -   S_(SECCLASS_KEY, KEY__LINK, "link") -   S_(SECCLASS_KEY, KEY__SETATTR, "setattr") -   S_(SECCLASS_KEY, KEY__CREATE, "create") -   S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") -   S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") -   S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") -   S_(SECCLASS_PEER, PEER__RECV, "recv") -   S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, "use_as_override") -   S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__CREATE_FILES_AS, "create_files_as") diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h deleted file mode 100644 index 0546d616cca..00000000000 --- a/security/selinux/include/av_permissions.h +++ /dev/null @@ -1,870 +0,0 @@ -/* This file is automatically generated.  Do not edit. */ -#define COMMON_FILE__IOCTL                               0x00000001UL -#define COMMON_FILE__READ                                0x00000002UL -#define COMMON_FILE__WRITE                               0x00000004UL -#define COMMON_FILE__CREATE                              0x00000008UL -#define COMMON_FILE__GETATTR                             0x00000010UL -#define COMMON_FILE__SETATTR                             0x00000020UL -#define COMMON_FILE__LOCK                                0x00000040UL -#define COMMON_FILE__RELABELFROM                         0x00000080UL -#define COMMON_FILE__RELABELTO                           0x00000100UL -#define COMMON_FILE__APPEND                              0x00000200UL -#define COMMON_FILE__UNLINK                              0x00000400UL -#define COMMON_FILE__LINK                                0x00000800UL -#define COMMON_FILE__RENAME                              0x00001000UL -#define COMMON_FILE__EXECUTE                             0x00002000UL -#define COMMON_FILE__SWAPON                              0x00004000UL -#define COMMON_FILE__QUOTAON                             0x00008000UL -#define COMMON_FILE__MOUNTON                             0x00010000UL -#define COMMON_SOCKET__IOCTL                             0x00000001UL -#define COMMON_SOCKET__READ                              0x00000002UL -#define COMMON_SOCKET__WRITE                             0x00000004UL -#define COMMON_SOCKET__CREATE                            0x00000008UL -#define COMMON_SOCKET__GETATTR                           0x00000010UL -#define COMMON_SOCKET__SETATTR                           0x00000020UL -#define COMMON_SOCKET__LOCK                              0x00000040UL -#define COMMON_SOCKET__RELABELFROM                       0x00000080UL -#define COMMON_SOCKET__RELABELTO                         0x00000100UL -#define COMMON_SOCKET__APPEND                            0x00000200UL -#define COMMON_SOCKET__BIND                              0x00000400UL -#define COMMON_SOCKET__CONNECT                           0x00000800UL -#define COMMON_SOCKET__LISTEN                            0x00001000UL -#define COMMON_SOCKET__ACCEPT                            0x00002000UL -#define COMMON_SOCKET__GETOPT                            0x00004000UL -#define COMMON_SOCKET__SETOPT                            0x00008000UL -#define COMMON_SOCKET__SHUTDOWN                          0x00010000UL -#define COMMON_SOCKET__RECVFROM                          0x00020000UL -#define COMMON_SOCKET__SENDTO                            0x00040000UL -#define COMMON_SOCKET__RECV_MSG                          0x00080000UL -#define COMMON_SOCKET__SEND_MSG                          0x00100000UL -#define COMMON_SOCKET__NAME_BIND                         0x00200000UL -#define COMMON_IPC__CREATE                               0x00000001UL -#define COMMON_IPC__DESTROY                              0x00000002UL -#define COMMON_IPC__GETATTR                              0x00000004UL -#define COMMON_IPC__SETATTR                              0x00000008UL -#define COMMON_IPC__READ                                 0x00000010UL -#define COMMON_IPC__WRITE                                0x00000020UL -#define COMMON_IPC__ASSOCIATE                            0x00000040UL -#define COMMON_IPC__UNIX_READ                            0x00000080UL -#define COMMON_IPC__UNIX_WRITE                           0x00000100UL -#define FILESYSTEM__MOUNT                         0x00000001UL -#define FILESYSTEM__REMOUNT                       0x00000002UL -#define FILESYSTEM__UNMOUNT                       0x00000004UL -#define FILESYSTEM__GETATTR                       0x00000008UL -#define FILESYSTEM__RELABELFROM                   0x00000010UL -#define FILESYSTEM__RELABELTO                     0x00000020UL -#define FILESYSTEM__TRANSITION                    0x00000040UL -#define FILESYSTEM__ASSOCIATE                     0x00000080UL -#define FILESYSTEM__QUOTAMOD                      0x00000100UL -#define FILESYSTEM__QUOTAGET                      0x00000200UL -#define DIR__IOCTL                                0x00000001UL -#define DIR__READ                                 0x00000002UL -#define DIR__WRITE                                0x00000004UL -#define DIR__CREATE                               0x00000008UL -#define DIR__GETATTR                              0x00000010UL -#define DIR__SETATTR                              0x00000020UL -#define DIR__LOCK                                 0x00000040UL -#define DIR__RELABELFROM                          0x00000080UL -#define DIR__RELABELTO                            0x00000100UL -#define DIR__APPEND                               0x00000200UL -#define DIR__UNLINK                               0x00000400UL -#define DIR__LINK                                 0x00000800UL -#define DIR__RENAME                               0x00001000UL -#define DIR__EXECUTE                              0x00002000UL -#define DIR__SWAPON                               0x00004000UL -#define DIR__QUOTAON                              0x00008000UL -#define DIR__MOUNTON                              0x00010000UL -#define DIR__ADD_NAME                             0x00020000UL -#define DIR__REMOVE_NAME                          0x00040000UL -#define DIR__REPARENT                             0x00080000UL -#define DIR__SEARCH                               0x00100000UL -#define DIR__RMDIR                                0x00200000UL -#define DIR__OPEN                                 0x00400000UL -#define FILE__IOCTL                               0x00000001UL -#define FILE__READ                                0x00000002UL -#define FILE__WRITE                               0x00000004UL -#define FILE__CREATE                              0x00000008UL -#define FILE__GETATTR                             0x00000010UL -#define FILE__SETATTR                             0x00000020UL -#define FILE__LOCK                                0x00000040UL -#define FILE__RELABELFROM                         0x00000080UL -#define FILE__RELABELTO                           0x00000100UL -#define FILE__APPEND                              0x00000200UL -#define FILE__UNLINK                              0x00000400UL -#define FILE__LINK                                0x00000800UL -#define FILE__RENAME                              0x00001000UL -#define FILE__EXECUTE                             0x00002000UL -#define FILE__SWAPON                              0x00004000UL -#define FILE__QUOTAON                             0x00008000UL -#define FILE__MOUNTON                             0x00010000UL -#define FILE__EXECUTE_NO_TRANS                    0x00020000UL -#define FILE__ENTRYPOINT                          0x00040000UL -#define FILE__EXECMOD                             0x00080000UL -#define FILE__OPEN                                0x00100000UL -#define LNK_FILE__IOCTL                           0x00000001UL -#define LNK_FILE__READ                            0x00000002UL -#define LNK_FILE__WRITE                           0x00000004UL -#define LNK_FILE__CREATE                          0x00000008UL -#define LNK_FILE__GETATTR                         0x00000010UL -#define LNK_FILE__SETATTR                         0x00000020UL -#define LNK_FILE__LOCK                            0x00000040UL -#define LNK_FILE__RELABELFROM                     0x00000080UL -#define LNK_FILE__RELABELTO                       0x00000100UL -#define LNK_FILE__APPEND                          0x00000200UL -#define LNK_FILE__UNLINK                          0x00000400UL -#define LNK_FILE__LINK                            0x00000800UL -#define LNK_FILE__RENAME                          0x00001000UL -#define LNK_FILE__EXECUTE                         0x00002000UL -#define LNK_FILE__SWAPON                          0x00004000UL -#define LNK_FILE__QUOTAON                         0x00008000UL -#define LNK_FILE__MOUNTON                         0x00010000UL -#define CHR_FILE__IOCTL                           0x00000001UL -#define CHR_FILE__READ                            0x00000002UL -#define CHR_FILE__WRITE                           0x00000004UL -#define CHR_FILE__CREATE                          0x00000008UL -#define CHR_FILE__GETATTR                         0x00000010UL -#define CHR_FILE__SETATTR                         0x00000020UL -#define CHR_FILE__LOCK                            0x00000040UL -#define CHR_FILE__RELABELFROM                     0x00000080UL -#define CHR_FILE__RELABELTO                       0x00000100UL -#define CHR_FILE__APPEND                          0x00000200UL -#define CHR_FILE__UNLINK                          0x00000400UL -#define CHR_FILE__LINK                            0x00000800UL -#define CHR_FILE__RENAME                          0x00001000UL -#define CHR_FILE__EXECUTE                         0x00002000UL -#define CHR_FILE__SWAPON                          0x00004000UL -#define CHR_FILE__QUOTAON                         0x00008000UL -#define CHR_FILE__MOUNTON                         0x00010000UL -#define CHR_FILE__EXECUTE_NO_TRANS                0x00020000UL -#define CHR_FILE__ENTRYPOINT                      0x00040000UL -#define CHR_FILE__EXECMOD                         0x00080000UL -#define CHR_FILE__OPEN                            0x00100000UL -#define BLK_FILE__IOCTL                           0x00000001UL -#define BLK_FILE__READ                            0x00000002UL -#define BLK_FILE__WRITE                           0x00000004UL -#define BLK_FILE__CREATE                          0x00000008UL -#define BLK_FILE__GETATTR                         0x00000010UL -#define BLK_FILE__SETATTR                         0x00000020UL -#define BLK_FILE__LOCK                            0x00000040UL -#define BLK_FILE__RELABELFROM                     0x00000080UL -#define BLK_FILE__RELABELTO                       0x00000100UL -#define BLK_FILE__APPEND                          0x00000200UL -#define BLK_FILE__UNLINK                          0x00000400UL -#define BLK_FILE__LINK                            0x00000800UL -#define BLK_FILE__RENAME                          0x00001000UL -#define BLK_FILE__EXECUTE                         0x00002000UL -#define BLK_FILE__SWAPON                          0x00004000UL -#define BLK_FILE__QUOTAON                         0x00008000UL -#define BLK_FILE__MOUNTON                         0x00010000UL -#define BLK_FILE__OPEN                            0x00020000UL -#define SOCK_FILE__IOCTL                          0x00000001UL -#define SOCK_FILE__READ                           0x00000002UL -#define SOCK_FILE__WRITE                          0x00000004UL -#define SOCK_FILE__CREATE                         0x00000008UL -#define SOCK_FILE__GETATTR                        0x00000010UL -#define SOCK_FILE__SETATTR                        0x00000020UL -#define SOCK_FILE__LOCK                           0x00000040UL -#define SOCK_FILE__RELABELFROM                    0x00000080UL -#define SOCK_FILE__RELABELTO                      0x00000100UL -#define SOCK_FILE__APPEND                         0x00000200UL -#define SOCK_FILE__UNLINK                         0x00000400UL -#define SOCK_FILE__LINK                           0x00000800UL -#define SOCK_FILE__RENAME                         0x00001000UL -#define SOCK_FILE__EXECUTE                        0x00002000UL -#define SOCK_FILE__SWAPON                         0x00004000UL -#define SOCK_FILE__QUOTAON                        0x00008000UL -#define SOCK_FILE__MOUNTON                        0x00010000UL -#define SOCK_FILE__OPEN                           0x00020000UL -#define FIFO_FILE__IOCTL                          0x00000001UL -#define FIFO_FILE__READ                           0x00000002UL -#define FIFO_FILE__WRITE                          0x00000004UL -#define FIFO_FILE__CREATE                         0x00000008UL -#define FIFO_FILE__GETATTR                        0x00000010UL -#define FIFO_FILE__SETATTR                        0x00000020UL -#define FIFO_FILE__LOCK                           0x00000040UL -#define FIFO_FILE__RELABELFROM                    0x00000080UL -#define FIFO_FILE__RELABELTO                      0x00000100UL -#define FIFO_FILE__APPEND                         0x00000200UL -#define FIFO_FILE__UNLINK                         0x00000400UL -#define FIFO_FILE__LINK                           0x00000800UL -#define FIFO_FILE__RENAME                         0x00001000UL -#define FIFO_FILE__EXECUTE                        0x00002000UL -#define FIFO_FILE__SWAPON                         0x00004000UL -#define FIFO_FILE__QUOTAON                        0x00008000UL -#define FIFO_FILE__MOUNTON                        0x00010000UL -#define FIFO_FILE__OPEN                           0x00020000UL -#define FD__USE                                   0x00000001UL -#define SOCKET__IOCTL                             0x00000001UL -#define SOCKET__READ                              0x00000002UL -#define SOCKET__WRITE                             0x00000004UL -#define SOCKET__CREATE                            0x00000008UL -#define SOCKET__GETATTR                           0x00000010UL -#define SOCKET__SETATTR                           0x00000020UL -#define SOCKET__LOCK                              0x00000040UL -#define SOCKET__RELABELFROM                       0x00000080UL -#define SOCKET__RELABELTO                         0x00000100UL -#define SOCKET__APPEND                            0x00000200UL -#define SOCKET__BIND                              0x00000400UL -#define SOCKET__CONNECT                           0x00000800UL -#define SOCKET__LISTEN                            0x00001000UL -#define SOCKET__ACCEPT                            0x00002000UL -#define SOCKET__GETOPT                            0x00004000UL -#define SOCKET__SETOPT                            0x00008000UL -#define SOCKET__SHUTDOWN                          0x00010000UL -#define SOCKET__RECVFROM                          0x00020000UL -#define SOCKET__SENDTO                            0x00040000UL -#define SOCKET__RECV_MSG                          0x00080000UL -#define SOCKET__SEND_MSG                          0x00100000UL -#define SOCKET__NAME_BIND                         0x00200000UL -#define TCP_SOCKET__IOCTL                         0x00000001UL -#define TCP_SOCKET__READ                          0x00000002UL -#define TCP_SOCKET__WRITE                         0x00000004UL -#define TCP_SOCKET__CREATE                        0x00000008UL -#define TCP_SOCKET__GETATTR                       0x00000010UL -#define TCP_SOCKET__SETATTR                       0x00000020UL -#define TCP_SOCKET__LOCK                          0x00000040UL -#define TCP_SOCKET__RELABELFROM                   0x00000080UL -#define TCP_SOCKET__RELABELTO                     0x00000100UL -#define TCP_SOCKET__APPEND                        0x00000200UL -#define TCP_SOCKET__BIND                          0x00000400UL -#define TCP_SOCKET__CONNECT                       0x00000800UL -#define TCP_SOCKET__LISTEN                        0x00001000UL -#define TCP_SOCKET__ACCEPT                        0x00002000UL -#define TCP_SOCKET__GETOPT                        0x00004000UL -#define TCP_SOCKET__SETOPT                        0x00008000UL -#define TCP_SOCKET__SHUTDOWN                      0x00010000UL -#define TCP_SOCKET__RECVFROM                      0x00020000UL -#define TCP_SOCKET__SENDTO                        0x00040000UL -#define TCP_SOCKET__RECV_MSG                      0x00080000UL -#define TCP_SOCKET__SEND_MSG                      0x00100000UL -#define TCP_SOCKET__NAME_BIND                     0x00200000UL -#define TCP_SOCKET__CONNECTTO                     0x00400000UL -#define TCP_SOCKET__NEWCONN                       0x00800000UL -#define TCP_SOCKET__ACCEPTFROM                    0x01000000UL -#define TCP_SOCKET__NODE_BIND                     0x02000000UL -#define TCP_SOCKET__NAME_CONNECT                  0x04000000UL -#define UDP_SOCKET__IOCTL                         0x00000001UL -#define UDP_SOCKET__READ                          0x00000002UL -#define UDP_SOCKET__WRITE                         0x00000004UL -#define UDP_SOCKET__CREATE                        0x00000008UL -#define UDP_SOCKET__GETATTR                       0x00000010UL -#define UDP_SOCKET__SETATTR                       0x00000020UL -#define UDP_SOCKET__LOCK                          0x00000040UL -#define UDP_SOCKET__RELABELFROM                   0x00000080UL -#define UDP_SOCKET__RELABELTO                     0x00000100UL -#define UDP_SOCKET__APPEND                        0x00000200UL -#define UDP_SOCKET__BIND                          0x00000400UL -#define UDP_SOCKET__CONNECT                       0x00000800UL -#define UDP_SOCKET__LISTEN                        0x00001000UL -#define UDP_SOCKET__ACCEPT                        0x00002000UL -#define UDP_SOCKET__GETOPT                        0x00004000UL -#define UDP_SOCKET__SETOPT                        0x00008000UL -#define UDP_SOCKET__SHUTDOWN                      0x00010000UL -#define UDP_SOCKET__RECVFROM                      0x00020000UL -#define UDP_SOCKET__SENDTO                        0x00040000UL -#define UDP_SOCKET__RECV_MSG                      0x00080000UL -#define UDP_SOCKET__SEND_MSG                      0x00100000UL -#define UDP_SOCKET__NAME_BIND                     0x00200000UL -#define UDP_SOCKET__NODE_BIND                     0x00400000UL -#define RAWIP_SOCKET__IOCTL                       0x00000001UL -#define RAWIP_SOCKET__READ                        0x00000002UL -#define RAWIP_SOCKET__WRITE                       0x00000004UL -#define RAWIP_SOCKET__CREATE                      0x00000008UL -#define RAWIP_SOCKET__GETATTR                     0x00000010UL -#define RAWIP_SOCKET__SETATTR                     0x00000020UL -#define RAWIP_SOCKET__LOCK                        0x00000040UL -#define RAWIP_SOCKET__RELABELFROM                 0x00000080UL -#define RAWIP_SOCKET__RELABELTO                   0x00000100UL -#define RAWIP_SOCKET__APPEND                      0x00000200UL -#define RAWIP_SOCKET__BIND                        0x00000400UL -#define RAWIP_SOCKET__CONNECT                     0x00000800UL -#define RAWIP_SOCKET__LISTEN                      0x00001000UL -#define RAWIP_SOCKET__ACCEPT                      0x00002000UL -#define RAWIP_SOCKET__GETOPT                      0x00004000UL -#define RAWIP_SOCKET__SETOPT                      0x00008000UL -#define RAWIP_SOCKET__SHUTDOWN                    0x00010000UL -#define RAWIP_SOCKET__RECVFROM                    0x00020000UL -#define RAWIP_SOCKET__SENDTO                      0x00040000UL -#define RAWIP_SOCKET__RECV_MSG                    0x00080000UL -#define RAWIP_SOCKET__SEND_MSG                    0x00100000UL -#define RAWIP_SOCKET__NAME_BIND                   0x00200000UL -#define RAWIP_SOCKET__NODE_BIND                   0x00400000UL -#define NODE__TCP_RECV                            0x00000001UL -#define NODE__TCP_SEND                            0x00000002UL -#define NODE__UDP_RECV                            0x00000004UL -#define NODE__UDP_SEND                            0x00000008UL -#define NODE__RAWIP_RECV                          0x00000010UL -#define NODE__RAWIP_SEND                          0x00000020UL -#define NODE__ENFORCE_DEST                        0x00000040UL -#define NODE__DCCP_RECV                           0x00000080UL -#define NODE__DCCP_SEND                           0x00000100UL -#define NODE__RECVFROM                            0x00000200UL -#define NODE__SENDTO                              0x00000400UL -#define NETIF__TCP_RECV                           0x00000001UL -#define NETIF__TCP_SEND                           0x00000002UL -#define NETIF__UDP_RECV                           0x00000004UL -#define NETIF__UDP_SEND                           0x00000008UL -#define NETIF__RAWIP_RECV                         0x00000010UL -#define NETIF__RAWIP_SEND                         0x00000020UL -#define NETIF__DCCP_RECV                          0x00000040UL -#define NETIF__DCCP_SEND                          0x00000080UL -#define NETIF__INGRESS                            0x00000100UL -#define NETIF__EGRESS                             0x00000200UL -#define NETLINK_SOCKET__IOCTL                     0x00000001UL -#define NETLINK_SOCKET__READ                      0x00000002UL -#define NETLINK_SOCKET__WRITE                     0x00000004UL -#define NETLINK_SOCKET__CREATE                    0x00000008UL -#define NETLINK_SOCKET__GETATTR                   0x00000010UL -#define NETLINK_SOCKET__SETATTR                   0x00000020UL -#define NETLINK_SOCKET__LOCK                      0x00000040UL -#define NETLINK_SOCKET__RELABELFROM               0x00000080UL -#define NETLINK_SOCKET__RELABELTO                 0x00000100UL -#define NETLINK_SOCKET__APPEND                    0x00000200UL -#define NETLINK_SOCKET__BIND                      0x00000400UL -#define NETLINK_SOCKET__CONNECT                   0x00000800UL -#define NETLINK_SOCKET__LISTEN                    0x00001000UL -#define NETLINK_SOCKET__ACCEPT                    0x00002000UL -#define NETLINK_SOCKET__GETOPT                    0x00004000UL -#define NETLINK_SOCKET__SETOPT                    0x00008000UL -#define NETLINK_SOCKET__SHUTDOWN                  0x00010000UL -#define NETLINK_SOCKET__RECVFROM                  0x00020000UL -#define NETLINK_SOCKET__SENDTO                    0x00040000UL -#define NETLINK_SOCKET__RECV_MSG                  0x00080000UL -#define NETLINK_SOCKET__SEND_MSG                  0x00100000UL -#define NETLINK_SOCKET__NAME_BIND                 0x00200000UL -#define PACKET_SOCKET__IOCTL                      0x00000001UL -#define PACKET_SOCKET__READ                       0x00000002UL -#define PACKET_SOCKET__WRITE                      0x00000004UL -#define PACKET_SOCKET__CREATE                     0x00000008UL -#define PACKET_SOCKET__GETATTR                    0x00000010UL -#define PACKET_SOCKET__SETATTR                    0x00000020UL -#define PACKET_SOCKET__LOCK                       0x00000040UL -#define PACKET_SOCKET__RELABELFROM                0x00000080UL -#define PACKET_SOCKET__RELABELTO                  0x00000100UL -#define PACKET_SOCKET__APPEND                     0x00000200UL -#define PACKET_SOCKET__BIND                       0x00000400UL -#define PACKET_SOCKET__CONNECT                    0x00000800UL -#define PACKET_SOCKET__LISTEN                     0x00001000UL -#define PACKET_SOCKET__ACCEPT                     0x00002000UL -#define PACKET_SOCKET__GETOPT                     0x00004000UL -#define PACKET_SOCKET__SETOPT                     0x00008000UL -#define PACKET_SOCKET__SHUTDOWN                   0x00010000UL -#define PACKET_SOCKET__RECVFROM                   0x00020000UL -#define PACKET_SOCKET__SENDTO                     0x00040000UL -#define PACKET_SOCKET__RECV_MSG                   0x00080000UL -#define PACKET_SOCKET__SEND_MSG                   0x00100000UL -#define PACKET_SOCKET__NAME_BIND                  0x00200000UL -#define KEY_SOCKET__IOCTL                         0x00000001UL -#define KEY_SOCKET__READ                          0x00000002UL -#define KEY_SOCKET__WRITE                         0x00000004UL -#define KEY_SOCKET__CREATE                        0x00000008UL -#define KEY_SOCKET__GETATTR                       0x00000010UL -#define KEY_SOCKET__SETATTR                       0x00000020UL -#define KEY_SOCKET__LOCK                          0x00000040UL -#define KEY_SOCKET__RELABELFROM                   0x00000080UL -#define KEY_SOCKET__RELABELTO                     0x00000100UL -#define KEY_SOCKET__APPEND                        0x00000200UL -#define KEY_SOCKET__BIND                          0x00000400UL -#define KEY_SOCKET__CONNECT                       0x00000800UL -#define KEY_SOCKET__LISTEN                        0x00001000UL -#define KEY_SOCKET__ACCEPT                        0x00002000UL -#define KEY_SOCKET__GETOPT                        0x00004000UL -#define KEY_SOCKET__SETOPT                        0x00008000UL -#define KEY_SOCKET__SHUTDOWN                      0x00010000UL -#define KEY_SOCKET__RECVFROM                      0x00020000UL -#define KEY_SOCKET__SENDTO                        0x00040000UL -#define KEY_SOCKET__RECV_MSG                      0x00080000UL -#define KEY_SOCKET__SEND_MSG                      0x00100000UL -#define KEY_SOCKET__NAME_BIND                     0x00200000UL -#define UNIX_STREAM_SOCKET__IOCTL                 0x00000001UL -#define UNIX_STREAM_SOCKET__READ                  0x00000002UL -#define UNIX_STREAM_SOCKET__WRITE                 0x00000004UL -#define UNIX_STREAM_SOCKET__CREATE                0x00000008UL -#define UNIX_STREAM_SOCKET__GETATTR               0x00000010UL -#define UNIX_STREAM_SOCKET__SETATTR               0x00000020UL -#define UNIX_STREAM_SOCKET__LOCK                  0x00000040UL -#define UNIX_STREAM_SOCKET__RELABELFROM           0x00000080UL -#define UNIX_STREAM_SOCKET__RELABELTO             0x00000100UL -#define UNIX_STREAM_SOCKET__APPEND                0x00000200UL -#define UNIX_STREAM_SOCKET__BIND                  0x00000400UL -#define UNIX_STREAM_SOCKET__CONNECT               0x00000800UL -#define UNIX_STREAM_SOCKET__LISTEN                0x00001000UL -#define UNIX_STREAM_SOCKET__ACCEPT                0x00002000UL -#define UNIX_STREAM_SOCKET__GETOPT                0x00004000UL -#define UNIX_STREAM_SOCKET__SETOPT                0x00008000UL -#define UNIX_STREAM_SOCKET__SHUTDOWN              0x00010000UL -#define UNIX_STREAM_SOCKET__RECVFROM              0x00020000UL -#define UNIX_STREAM_SOCKET__SENDTO                0x00040000UL -#define UNIX_STREAM_SOCKET__RECV_MSG              0x00080000UL -#define UNIX_STREAM_SOCKET__SEND_MSG              0x00100000UL -#define UNIX_STREAM_SOCKET__NAME_BIND             0x00200000UL -#define UNIX_STREAM_SOCKET__CONNECTTO             0x00400000UL -#define UNIX_STREAM_SOCKET__NEWCONN               0x00800000UL -#define UNIX_STREAM_SOCKET__ACCEPTFROM            0x01000000UL -#define UNIX_DGRAM_SOCKET__IOCTL                  0x00000001UL -#define UNIX_DGRAM_SOCKET__READ                   0x00000002UL -#define UNIX_DGRAM_SOCKET__WRITE                  0x00000004UL -#define UNIX_DGRAM_SOCKET__CREATE                 0x00000008UL -#define UNIX_DGRAM_SOCKET__GETATTR                0x00000010UL -#define UNIX_DGRAM_SOCKET__SETATTR                0x00000020UL -#define UNIX_DGRAM_SOCKET__LOCK                   0x00000040UL -#define UNIX_DGRAM_SOCKET__RELABELFROM            0x00000080UL -#define UNIX_DGRAM_SOCKET__RELABELTO              0x00000100UL -#define UNIX_DGRAM_SOCKET__APPEND                 0x00000200UL -#define UNIX_DGRAM_SOCKET__BIND                   0x00000400UL -#define UNIX_DGRAM_SOCKET__CONNECT                0x00000800UL -#define UNIX_DGRAM_SOCKET__LISTEN                 0x00001000UL -#define UNIX_DGRAM_SOCKET__ACCEPT                 0x00002000UL -#define UNIX_DGRAM_SOCKET__GETOPT                 0x00004000UL -#define UNIX_DGRAM_SOCKET__SETOPT                 0x00008000UL -#define UNIX_DGRAM_SOCKET__SHUTDOWN               0x00010000UL -#define UNIX_DGRAM_SOCKET__RECVFROM               0x00020000UL -#define UNIX_DGRAM_SOCKET__SENDTO                 0x00040000UL -#define UNIX_DGRAM_SOCKET__RECV_MSG               0x00080000UL -#define UNIX_DGRAM_SOCKET__SEND_MSG               0x00100000UL -#define UNIX_DGRAM_SOCKET__NAME_BIND              0x00200000UL -#define TUN_SOCKET__IOCTL                         0x00000001UL -#define TUN_SOCKET__READ                          0x00000002UL -#define TUN_SOCKET__WRITE                         0x00000004UL -#define TUN_SOCKET__CREATE                        0x00000008UL -#define TUN_SOCKET__GETATTR                       0x00000010UL -#define TUN_SOCKET__SETATTR                       0x00000020UL -#define TUN_SOCKET__LOCK                          0x00000040UL -#define TUN_SOCKET__RELABELFROM                   0x00000080UL -#define TUN_SOCKET__RELABELTO                     0x00000100UL -#define TUN_SOCKET__APPEND                        0x00000200UL -#define TUN_SOCKET__BIND                          0x00000400UL -#define TUN_SOCKET__CONNECT                       0x00000800UL -#define TUN_SOCKET__LISTEN                        0x00001000UL -#define TUN_SOCKET__ACCEPT                        0x00002000UL -#define TUN_SOCKET__GETOPT                        0x00004000UL -#define TUN_SOCKET__SETOPT                        0x00008000UL -#define TUN_SOCKET__SHUTDOWN                      0x00010000UL -#define TUN_SOCKET__RECVFROM                      0x00020000UL -#define TUN_SOCKET__SENDTO                        0x00040000UL -#define TUN_SOCKET__RECV_MSG                      0x00080000UL -#define TUN_SOCKET__SEND_MSG                      0x00100000UL -#define TUN_SOCKET__NAME_BIND                     0x00200000UL -#define PROCESS__FORK                             0x00000001UL -#define PROCESS__TRANSITION                       0x00000002UL -#define PROCESS__SIGCHLD                          0x00000004UL -#define PROCESS__SIGKILL                          0x00000008UL -#define PROCESS__SIGSTOP                          0x00000010UL -#define PROCESS__SIGNULL                          0x00000020UL -#define PROCESS__SIGNAL                           0x00000040UL -#define PROCESS__PTRACE                           0x00000080UL -#define PROCESS__GETSCHED                         0x00000100UL -#define PROCESS__SETSCHED                         0x00000200UL -#define PROCESS__GETSESSION                       0x00000400UL -#define PROCESS__GETPGID                          0x00000800UL -#define PROCESS__SETPGID                          0x00001000UL -#define PROCESS__GETCAP                           0x00002000UL -#define PROCESS__SETCAP                           0x00004000UL -#define PROCESS__SHARE                            0x00008000UL -#define PROCESS__GETATTR                          0x00010000UL -#define PROCESS__SETEXEC                          0x00020000UL -#define PROCESS__SETFSCREATE                      0x00040000UL -#define PROCESS__NOATSECURE                       0x00080000UL -#define PROCESS__SIGINH                           0x00100000UL -#define PROCESS__SETRLIMIT                        0x00200000UL -#define PROCESS__RLIMITINH                        0x00400000UL -#define PROCESS__DYNTRANSITION                    0x00800000UL -#define PROCESS__SETCURRENT                       0x01000000UL -#define PROCESS__EXECMEM                          0x02000000UL -#define PROCESS__EXECSTACK                        0x04000000UL -#define PROCESS__EXECHEAP                         0x08000000UL -#define PROCESS__SETKEYCREATE                     0x10000000UL -#define PROCESS__SETSOCKCREATE                    0x20000000UL -#define IPC__CREATE                               0x00000001UL -#define IPC__DESTROY                              0x00000002UL -#define IPC__GETATTR                              0x00000004UL -#define IPC__SETATTR                              0x00000008UL -#define IPC__READ                                 0x00000010UL -#define IPC__WRITE                                0x00000020UL -#define IPC__ASSOCIATE                            0x00000040UL -#define IPC__UNIX_READ                            0x00000080UL -#define IPC__UNIX_WRITE                           0x00000100UL -#define SEM__CREATE                               0x00000001UL -#define SEM__DESTROY                              0x00000002UL -#define SEM__GETATTR                              0x00000004UL -#define SEM__SETATTR                              0x00000008UL -#define SEM__READ                                 0x00000010UL -#define SEM__WRITE                                0x00000020UL -#define SEM__ASSOCIATE                            0x00000040UL -#define SEM__UNIX_READ                            0x00000080UL -#define SEM__UNIX_WRITE                           0x00000100UL -#define MSGQ__CREATE                              0x00000001UL -#define MSGQ__DESTROY                             0x00000002UL -#define MSGQ__GETATTR                             0x00000004UL -#define MSGQ__SETATTR                             0x00000008UL -#define MSGQ__READ                                0x00000010UL -#define MSGQ__WRITE                               0x00000020UL -#define MSGQ__ASSOCIATE                           0x00000040UL -#define MSGQ__UNIX_READ                           0x00000080UL -#define MSGQ__UNIX_WRITE                          0x00000100UL -#define MSGQ__ENQUEUE                             0x00000200UL -#define MSG__SEND                                 0x00000001UL -#define MSG__RECEIVE                              0x00000002UL -#define SHM__CREATE                               0x00000001UL -#define SHM__DESTROY                              0x00000002UL -#define SHM__GETATTR                              0x00000004UL -#define SHM__SETATTR                              0x00000008UL -#define SHM__READ                                 0x00000010UL -#define SHM__WRITE                                0x00000020UL -#define SHM__ASSOCIATE                            0x00000040UL -#define SHM__UNIX_READ                            0x00000080UL -#define SHM__UNIX_WRITE                           0x00000100UL -#define SHM__LOCK                                 0x00000200UL -#define SECURITY__COMPUTE_AV                      0x00000001UL -#define SECURITY__COMPUTE_CREATE                  0x00000002UL -#define SECURITY__COMPUTE_MEMBER                  0x00000004UL -#define SECURITY__CHECK_CONTEXT                   0x00000008UL -#define SECURITY__LOAD_POLICY                     0x00000010UL -#define SECURITY__COMPUTE_RELABEL                 0x00000020UL -#define SECURITY__COMPUTE_USER                    0x00000040UL -#define SECURITY__SETENFORCE                      0x00000080UL -#define SECURITY__SETBOOL                         0x00000100UL -#define SECURITY__SETSECPARAM                     0x00000200UL -#define SECURITY__SETCHECKREQPROT                 0x00000400UL -#define SYSTEM__IPC_INFO                          0x00000001UL -#define SYSTEM__SYSLOG_READ                       0x00000002UL -#define SYSTEM__SYSLOG_MOD                        0x00000004UL -#define SYSTEM__SYSLOG_CONSOLE                    0x00000008UL -#define SYSTEM__MODULE_REQUEST                    0x00000010UL -#define CAPABILITY__CHOWN                         0x00000001UL -#define CAPABILITY__DAC_OVERRIDE                  0x00000002UL -#define CAPABILITY__DAC_READ_SEARCH               0x00000004UL -#define CAPABILITY__FOWNER                        0x00000008UL -#define CAPABILITY__FSETID                        0x00000010UL -#define CAPABILITY__KILL                          0x00000020UL -#define CAPABILITY__SETGID                        0x00000040UL -#define CAPABILITY__SETUID                        0x00000080UL -#define CAPABILITY__SETPCAP                       0x00000100UL -#define CAPABILITY__LINUX_IMMUTABLE               0x00000200UL -#define CAPABILITY__NET_BIND_SERVICE              0x00000400UL -#define CAPABILITY__NET_BROADCAST                 0x00000800UL -#define CAPABILITY__NET_ADMIN                     0x00001000UL -#define CAPABILITY__NET_RAW                       0x00002000UL -#define CAPABILITY__IPC_LOCK                      0x00004000UL -#define CAPABILITY__IPC_OWNER                     0x00008000UL -#define CAPABILITY__SYS_MODULE                    0x00010000UL -#define CAPABILITY__SYS_RAWIO                     0x00020000UL -#define CAPABILITY__SYS_CHROOT                    0x00040000UL -#define CAPABILITY__SYS_PTRACE                    0x00080000UL -#define CAPABILITY__SYS_PACCT                     0x00100000UL -#define CAPABILITY__SYS_ADMIN                     0x00200000UL -#define CAPABILITY__SYS_BOOT                      0x00400000UL -#define CAPABILITY__SYS_NICE                      0x00800000UL -#define CAPABILITY__SYS_RESOURCE                  0x01000000UL -#define CAPABILITY__SYS_TIME                      0x02000000UL -#define CAPABILITY__SYS_TTY_CONFIG                0x04000000UL -#define CAPABILITY__MKNOD                         0x08000000UL -#define CAPABILITY__LEASE                         0x10000000UL -#define CAPABILITY__AUDIT_WRITE                   0x20000000UL -#define CAPABILITY__AUDIT_CONTROL                 0x40000000UL -#define CAPABILITY__SETFCAP                       0x80000000UL -#define CAPABILITY2__MAC_OVERRIDE                 0x00000001UL -#define CAPABILITY2__MAC_ADMIN                    0x00000002UL -#define NETLINK_ROUTE_SOCKET__IOCTL               0x00000001UL -#define NETLINK_ROUTE_SOCKET__READ                0x00000002UL -#define NETLINK_ROUTE_SOCKET__WRITE               0x00000004UL -#define NETLINK_ROUTE_SOCKET__CREATE              0x00000008UL -#define NETLINK_ROUTE_SOCKET__GETATTR             0x00000010UL -#define NETLINK_ROUTE_SOCKET__SETATTR             0x00000020UL -#define NETLINK_ROUTE_SOCKET__LOCK                0x00000040UL -#define NETLINK_ROUTE_SOCKET__RELABELFROM         0x00000080UL -#define NETLINK_ROUTE_SOCKET__RELABELTO           0x00000100UL -#define NETLINK_ROUTE_SOCKET__APPEND              0x00000200UL -#define NETLINK_ROUTE_SOCKET__BIND                0x00000400UL -#define NETLINK_ROUTE_SOCKET__CONNECT             0x00000800UL -#define NETLINK_ROUTE_SOCKET__LISTEN              0x00001000UL -#define NETLINK_ROUTE_SOCKET__ACCEPT              0x00002000UL -#define NETLINK_ROUTE_SOCKET__GETOPT              0x00004000UL -#define NETLINK_ROUTE_SOCKET__SETOPT              0x00008000UL -#define NETLINK_ROUTE_SOCKET__SHUTDOWN            0x00010000UL -#define NETLINK_ROUTE_SOCKET__RECVFROM            0x00020000UL -#define NETLINK_ROUTE_SOCKET__SENDTO              0x00040000UL -#define NETLINK_ROUTE_SOCKET__RECV_MSG            0x00080000UL -#define NETLINK_ROUTE_SOCKET__SEND_MSG            0x00100000UL -#define NETLINK_ROUTE_SOCKET__NAME_BIND           0x00200000UL -#define NETLINK_ROUTE_SOCKET__NLMSG_READ          0x00400000UL -#define NETLINK_ROUTE_SOCKET__NLMSG_WRITE         0x00800000UL -#define NETLINK_FIREWALL_SOCKET__IOCTL            0x00000001UL -#define NETLINK_FIREWALL_SOCKET__READ             0x00000002UL -#define NETLINK_FIREWALL_SOCKET__WRITE            0x00000004UL -#define NETLINK_FIREWALL_SOCKET__CREATE           0x00000008UL -#define NETLINK_FIREWALL_SOCKET__GETATTR          0x00000010UL -#define NETLINK_FIREWALL_SOCKET__SETATTR          0x00000020UL -#define NETLINK_FIREWALL_SOCKET__LOCK             0x00000040UL -#define NETLINK_FIREWALL_SOCKET__RELABELFROM      0x00000080UL -#define NETLINK_FIREWALL_SOCKET__RELABELTO        0x00000100UL -#define NETLINK_FIREWALL_SOCKET__APPEND           0x00000200UL -#define NETLINK_FIREWALL_SOCKET__BIND             0x00000400UL -#define NETLINK_FIREWALL_SOCKET__CONNECT          0x00000800UL -#define NETLINK_FIREWALL_SOCKET__LISTEN           0x00001000UL -#define NETLINK_FIREWALL_SOCKET__ACCEPT           0x00002000UL -#define NETLINK_FIREWALL_SOCKET__GETOPT           0x00004000UL -#define NETLINK_FIREWALL_SOCKET__SETOPT           0x00008000UL -#define NETLINK_FIREWALL_SOCKET__SHUTDOWN         0x00010000UL -#define NETLINK_FIREWALL_SOCKET__RECVFROM         0x00020000UL -#define NETLINK_FIREWALL_SOCKET__SENDTO           0x00040000UL -#define NETLINK_FIREWALL_SOCKET__RECV_MSG         0x00080000UL -#define NETLINK_FIREWALL_SOCKET__SEND_MSG         0x00100000UL -#define NETLINK_FIREWALL_SOCKET__NAME_BIND        0x00200000UL -#define NETLINK_FIREWALL_SOCKET__NLMSG_READ       0x00400000UL -#define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE      0x00800000UL -#define NETLINK_TCPDIAG_SOCKET__IOCTL             0x00000001UL -#define NETLINK_TCPDIAG_SOCKET__READ              0x00000002UL -#define NETLINK_TCPDIAG_SOCKET__WRITE             0x00000004UL -#define NETLINK_TCPDIAG_SOCKET__CREATE            0x00000008UL -#define NETLINK_TCPDIAG_SOCKET__GETATTR           0x00000010UL -#define NETLINK_TCPDIAG_SOCKET__SETATTR           0x00000020UL -#define NETLINK_TCPDIAG_SOCKET__LOCK              0x00000040UL -#define NETLINK_TCPDIAG_SOCKET__RELABELFROM       0x00000080UL -#define NETLINK_TCPDIAG_SOCKET__RELABELTO         0x00000100UL -#define NETLINK_TCPDIAG_SOCKET__APPEND            0x00000200UL -#define NETLINK_TCPDIAG_SOCKET__BIND              0x00000400UL -#define NETLINK_TCPDIAG_SOCKET__CONNECT           0x00000800UL -#define NETLINK_TCPDIAG_SOCKET__LISTEN            0x00001000UL -#define NETLINK_TCPDIAG_SOCKET__ACCEPT            0x00002000UL -#define NETLINK_TCPDIAG_SOCKET__GETOPT            0x00004000UL -#define NETLINK_TCPDIAG_SOCKET__SETOPT            0x00008000UL -#define NETLINK_TCPDIAG_SOCKET__SHUTDOWN          0x00010000UL -#define NETLINK_TCPDIAG_SOCKET__RECVFROM          0x00020000UL -#define NETLINK_TCPDIAG_SOCKET__SENDTO            0x00040000UL -#define NETLINK_TCPDIAG_SOCKET__RECV_MSG          0x00080000UL -#define NETLINK_TCPDIAG_SOCKET__SEND_MSG          0x00100000UL -#define NETLINK_TCPDIAG_SOCKET__NAME_BIND         0x00200000UL -#define NETLINK_TCPDIAG_SOCKET__NLMSG_READ        0x00400000UL -#define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE       0x00800000UL -#define NETLINK_NFLOG_SOCKET__IOCTL               0x00000001UL -#define NETLINK_NFLOG_SOCKET__READ                0x00000002UL -#define NETLINK_NFLOG_SOCKET__WRITE               0x00000004UL -#define NETLINK_NFLOG_SOCKET__CREATE              0x00000008UL -#define NETLINK_NFLOG_SOCKET__GETATTR             0x00000010UL -#define NETLINK_NFLOG_SOCKET__SETATTR             0x00000020UL -#define NETLINK_NFLOG_SOCKET__LOCK                0x00000040UL -#define NETLINK_NFLOG_SOCKET__RELABELFROM         0x00000080UL -#define NETLINK_NFLOG_SOCKET__RELABELTO           0x00000100UL -#define NETLINK_NFLOG_SOCKET__APPEND              0x00000200UL -#define NETLINK_NFLOG_SOCKET__BIND                0x00000400UL -#define NETLINK_NFLOG_SOCKET__CONNECT             0x00000800UL -#define NETLINK_NFLOG_SOCKET__LISTEN              0x00001000UL -#define NETLINK_NFLOG_SOCKET__ACCEPT              0x00002000UL -#define NETLINK_NFLOG_SOCKET__GETOPT              0x00004000UL -#define NETLINK_NFLOG_SOCKET__SETOPT              0x00008000UL -#define NETLINK_NFLOG_SOCKET__SHUTDOWN            0x00010000UL -#define NETLINK_NFLOG_SOCKET__RECVFROM            0x00020000UL -#define NETLINK_NFLOG_SOCKET__SENDTO              0x00040000UL -#define NETLINK_NFLOG_SOCKET__RECV_MSG            0x00080000UL -#define NETLINK_NFLOG_SOCKET__SEND_MSG            0x00100000UL -#define NETLINK_NFLOG_SOCKET__NAME_BIND           0x00200000UL -#define NETLINK_XFRM_SOCKET__IOCTL                0x00000001UL -#define NETLINK_XFRM_SOCKET__READ                 0x00000002UL -#define NETLINK_XFRM_SOCKET__WRITE                0x00000004UL -#define NETLINK_XFRM_SOCKET__CREATE               0x00000008UL -#define NETLINK_XFRM_SOCKET__GETATTR              0x00000010UL -#define NETLINK_XFRM_SOCKET__SETATTR              0x00000020UL -#define NETLINK_XFRM_SOCKET__LOCK                 0x00000040UL -#define NETLINK_XFRM_SOCKET__RELABELFROM          0x00000080UL -#define NETLINK_XFRM_SOCKET__RELABELTO            0x00000100UL -#define NETLINK_XFRM_SOCKET__APPEND               0x00000200UL -#define NETLINK_XFRM_SOCKET__BIND                 0x00000400UL -#define NETLINK_XFRM_SOCKET__CONNECT              0x00000800UL -#define NETLINK_XFRM_SOCKET__LISTEN               0x00001000UL -#define NETLINK_XFRM_SOCKET__ACCEPT               0x00002000UL -#define NETLINK_XFRM_SOCKET__GETOPT               0x00004000UL -#define NETLINK_XFRM_SOCKET__SETOPT               0x00008000UL -#define NETLINK_XFRM_SOCKET__SHUTDOWN             0x00010000UL -#define NETLINK_XFRM_SOCKET__RECVFROM             0x00020000UL -#define NETLINK_XFRM_SOCKET__SENDTO               0x00040000UL -#define NETLINK_XFRM_SOCKET__RECV_MSG             0x00080000UL -#define NETLINK_XFRM_SOCKET__SEND_MSG             0x00100000UL -#define NETLINK_XFRM_SOCKET__NAME_BIND            0x00200000UL -#define NETLINK_XFRM_SOCKET__NLMSG_READ           0x00400000UL -#define NETLINK_XFRM_SOCKET__NLMSG_WRITE          0x00800000UL -#define NETLINK_SELINUX_SOCKET__IOCTL             0x00000001UL -#define NETLINK_SELINUX_SOCKET__READ              0x00000002UL -#define NETLINK_SELINUX_SOCKET__WRITE             0x00000004UL -#define NETLINK_SELINUX_SOCKET__CREATE            0x00000008UL -#define NETLINK_SELINUX_SOCKET__GETATTR           0x00000010UL -#define NETLINK_SELINUX_SOCKET__SETATTR           0x00000020UL -#define NETLINK_SELINUX_SOCKET__LOCK              0x00000040UL -#define NETLINK_SELINUX_SOCKET__RELABELFROM       0x00000080UL -#define NETLINK_SELINUX_SOCKET__RELABELTO         0x00000100UL -#define NETLINK_SELINUX_SOCKET__APPEND            0x00000200UL -#define NETLINK_SELINUX_SOCKET__BIND              0x00000400UL -#define NETLINK_SELINUX_SOCKET__CONNECT           0x00000800UL -#define NETLINK_SELINUX_SOCKET__LISTEN            0x00001000UL -#define NETLINK_SELINUX_SOCKET__ACCEPT            0x00002000UL -#define NETLINK_SELINUX_SOCKET__GETOPT            0x00004000UL -#define NETLINK_SELINUX_SOCKET__SETOPT            0x00008000UL -#define NETLINK_SELINUX_SOCKET__SHUTDOWN          0x00010000UL -#define NETLINK_SELINUX_SOCKET__RECVFROM          0x00020000UL -#define NETLINK_SELINUX_SOCKET__SENDTO            0x00040000UL -#define NETLINK_SELINUX_SOCKET__RECV_MSG          0x00080000UL -#define NETLINK_SELINUX_SOCKET__SEND_MSG          0x00100000UL -#define NETLINK_SELINUX_SOCKET__NAME_BIND         0x00200000UL -#define NETLINK_AUDIT_SOCKET__IOCTL               0x00000001UL -#define NETLINK_AUDIT_SOCKET__READ                0x00000002UL -#define NETLINK_AUDIT_SOCKET__WRITE               0x00000004UL -#define NETLINK_AUDIT_SOCKET__CREATE              0x00000008UL -#define NETLINK_AUDIT_SOCKET__GETATTR             0x00000010UL -#define NETLINK_AUDIT_SOCKET__SETATTR             0x00000020UL -#define NETLINK_AUDIT_SOCKET__LOCK                0x00000040UL -#define NETLINK_AUDIT_SOCKET__RELABELFROM         0x00000080UL -#define NETLINK_AUDIT_SOCKET__RELABELTO           0x00000100UL -#define NETLINK_AUDIT_SOCKET__APPEND              0x00000200UL -#define NETLINK_AUDIT_SOCKET__BIND                0x00000400UL -#define NETLINK_AUDIT_SOCKET__CONNECT             0x00000800UL -#define NETLINK_AUDIT_SOCKET__LISTEN              0x00001000UL -#define NETLINK_AUDIT_SOCKET__ACCEPT              0x00002000UL -#define NETLINK_AUDIT_SOCKET__GETOPT              0x00004000UL -#define NETLINK_AUDIT_SOCKET__SETOPT              0x00008000UL -#define NETLINK_AUDIT_SOCKET__SHUTDOWN            0x00010000UL -#define NETLINK_AUDIT_SOCKET__RECVFROM            0x00020000UL -#define NETLINK_AUDIT_SOCKET__SENDTO              0x00040000UL -#define NETLINK_AUDIT_SOCKET__RECV_MSG            0x00080000UL -#define NETLINK_AUDIT_SOCKET__SEND_MSG            0x00100000UL -#define NETLINK_AUDIT_SOCKET__NAME_BIND           0x00200000UL -#define NETLINK_AUDIT_SOCKET__NLMSG_READ          0x00400000UL -#define NETLINK_AUDIT_SOCKET__NLMSG_WRITE         0x00800000UL -#define NETLINK_AUDIT_SOCKET__NLMSG_RELAY         0x01000000UL -#define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV      0x02000000UL -#define NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT     0x04000000UL -#define NETLINK_IP6FW_SOCKET__IOCTL               0x00000001UL -#define NETLINK_IP6FW_SOCKET__READ                0x00000002UL -#define NETLINK_IP6FW_SOCKET__WRITE               0x00000004UL -#define NETLINK_IP6FW_SOCKET__CREATE              0x00000008UL -#define NETLINK_IP6FW_SOCKET__GETATTR             0x00000010UL -#define NETLINK_IP6FW_SOCKET__SETATTR             0x00000020UL -#define NETLINK_IP6FW_SOCKET__LOCK                0x00000040UL -#define NETLINK_IP6FW_SOCKET__RELABELFROM         0x00000080UL -#define NETLINK_IP6FW_SOCKET__RELABELTO           0x00000100UL -#define NETLINK_IP6FW_SOCKET__APPEND              0x00000200UL -#define NETLINK_IP6FW_SOCKET__BIND                0x00000400UL -#define NETLINK_IP6FW_SOCKET__CONNECT             0x00000800UL -#define NETLINK_IP6FW_SOCKET__LISTEN              0x00001000UL -#define NETLINK_IP6FW_SOCKET__ACCEPT              0x00002000UL -#define NETLINK_IP6FW_SOCKET__GETOPT              0x00004000UL -#define NETLINK_IP6FW_SOCKET__SETOPT              0x00008000UL -#define NETLINK_IP6FW_SOCKET__SHUTDOWN            0x00010000UL -#define NETLINK_IP6FW_SOCKET__RECVFROM            0x00020000UL -#define NETLINK_IP6FW_SOCKET__SENDTO              0x00040000UL -#define NETLINK_IP6FW_SOCKET__RECV_MSG            0x00080000UL -#define NETLINK_IP6FW_SOCKET__SEND_MSG            0x00100000UL -#define NETLINK_IP6FW_SOCKET__NAME_BIND           0x00200000UL -#define NETLINK_IP6FW_SOCKET__NLMSG_READ          0x00400000UL -#define NETLINK_IP6FW_SOCKET__NLMSG_WRITE         0x00800000UL -#define NETLINK_DNRT_SOCKET__IOCTL                0x00000001UL -#define NETLINK_DNRT_SOCKET__READ                 0x00000002UL -#define NETLINK_DNRT_SOCKET__WRITE                0x00000004UL -#define NETLINK_DNRT_SOCKET__CREATE               0x00000008UL -#define NETLINK_DNRT_SOCKET__GETATTR              0x00000010UL -#define NETLINK_DNRT_SOCKET__SETATTR              0x00000020UL -#define NETLINK_DNRT_SOCKET__LOCK                 0x00000040UL -#define NETLINK_DNRT_SOCKET__RELABELFROM          0x00000080UL -#define NETLINK_DNRT_SOCKET__RELABELTO            0x00000100UL -#define NETLINK_DNRT_SOCKET__APPEND               0x00000200UL -#define NETLINK_DNRT_SOCKET__BIND                 0x00000400UL -#define NETLINK_DNRT_SOCKET__CONNECT              0x00000800UL -#define NETLINK_DNRT_SOCKET__LISTEN               0x00001000UL -#define NETLINK_DNRT_SOCKET__ACCEPT               0x00002000UL -#define NETLINK_DNRT_SOCKET__GETOPT               0x00004000UL -#define NETLINK_DNRT_SOCKET__SETOPT               0x00008000UL -#define NETLINK_DNRT_SOCKET__SHUTDOWN             0x00010000UL -#define NETLINK_DNRT_SOCKET__RECVFROM             0x00020000UL -#define NETLINK_DNRT_SOCKET__SENDTO               0x00040000UL -#define NETLINK_DNRT_SOCKET__RECV_MSG             0x00080000UL -#define NETLINK_DNRT_SOCKET__SEND_MSG             0x00100000UL -#define NETLINK_DNRT_SOCKET__NAME_BIND            0x00200000UL -#define ASSOCIATION__SENDTO                       0x00000001UL -#define ASSOCIATION__RECVFROM                     0x00000002UL -#define ASSOCIATION__SETCONTEXT                   0x00000004UL -#define ASSOCIATION__POLMATCH                     0x00000008UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL      0x00000001UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__READ       0x00000002UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__WRITE      0x00000004UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__CREATE     0x00000008UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__GETATTR    0x00000010UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__SETATTR    0x00000020UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__LOCK       0x00000040UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELFROM 0x00000080UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELTO  0x00000100UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__APPEND     0x00000200UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__BIND       0x00000400UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__CONNECT    0x00000800UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__LISTEN     0x00001000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__ACCEPT     0x00002000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__GETOPT     0x00004000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__SETOPT     0x00008000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__SHUTDOWN   0x00010000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__RECVFROM   0x00020000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__SENDTO     0x00040000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__RECV_MSG   0x00080000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG   0x00100000UL -#define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND  0x00200000UL -#define APPLETALK_SOCKET__IOCTL                   0x00000001UL -#define APPLETALK_SOCKET__READ                    0x00000002UL -#define APPLETALK_SOCKET__WRITE                   0x00000004UL -#define APPLETALK_SOCKET__CREATE                  0x00000008UL -#define APPLETALK_SOCKET__GETATTR                 0x00000010UL -#define APPLETALK_SOCKET__SETATTR                 0x00000020UL -#define APPLETALK_SOCKET__LOCK                    0x00000040UL -#define APPLETALK_SOCKET__RELABELFROM             0x00000080UL -#define APPLETALK_SOCKET__RELABELTO               0x00000100UL -#define APPLETALK_SOCKET__APPEND                  0x00000200UL -#define APPLETALK_SOCKET__BIND                    0x00000400UL -#define APPLETALK_SOCKET__CONNECT                 0x00000800UL -#define APPLETALK_SOCKET__LISTEN                  0x00001000UL -#define APPLETALK_SOCKET__ACCEPT                  0x00002000UL -#define APPLETALK_SOCKET__GETOPT                  0x00004000UL -#define APPLETALK_SOCKET__SETOPT                  0x00008000UL -#define APPLETALK_SOCKET__SHUTDOWN                0x00010000UL -#define APPLETALK_SOCKET__RECVFROM                0x00020000UL -#define APPLETALK_SOCKET__SENDTO                  0x00040000UL -#define APPLETALK_SOCKET__RECV_MSG                0x00080000UL -#define APPLETALK_SOCKET__SEND_MSG                0x00100000UL -#define APPLETALK_SOCKET__NAME_BIND               0x00200000UL -#define PACKET__SEND                              0x00000001UL -#define PACKET__RECV                              0x00000002UL -#define PACKET__RELABELTO                         0x00000004UL -#define PACKET__FLOW_IN                           0x00000008UL -#define PACKET__FLOW_OUT                          0x00000010UL -#define PACKET__FORWARD_IN                        0x00000020UL -#define PACKET__FORWARD_OUT                       0x00000040UL -#define KEY__VIEW                                 0x00000001UL -#define KEY__READ                                 0x00000002UL -#define KEY__WRITE                                0x00000004UL -#define KEY__SEARCH                               0x00000008UL -#define KEY__LINK                                 0x00000010UL -#define KEY__SETATTR                              0x00000020UL -#define KEY__CREATE                               0x00000040UL -#define DCCP_SOCKET__IOCTL                        0x00000001UL -#define DCCP_SOCKET__READ                         0x00000002UL -#define DCCP_SOCKET__WRITE                        0x00000004UL -#define DCCP_SOCKET__CREATE                       0x00000008UL -#define DCCP_SOCKET__GETATTR                      0x00000010UL -#define DCCP_SOCKET__SETATTR                      0x00000020UL -#define DCCP_SOCKET__LOCK                         0x00000040UL -#define DCCP_SOCKET__RELABELFROM                  0x00000080UL -#define DCCP_SOCKET__RELABELTO                    0x00000100UL -#define DCCP_SOCKET__APPEND                       0x00000200UL -#define DCCP_SOCKET__BIND                         0x00000400UL -#define DCCP_SOCKET__CONNECT                      0x00000800UL -#define DCCP_SOCKET__LISTEN                       0x00001000UL -#define DCCP_SOCKET__ACCEPT                       0x00002000UL -#define DCCP_SOCKET__GETOPT                       0x00004000UL -#define DCCP_SOCKET__SETOPT                       0x00008000UL -#define DCCP_SOCKET__SHUTDOWN                     0x00010000UL -#define DCCP_SOCKET__RECVFROM                     0x00020000UL -#define DCCP_SOCKET__SENDTO                       0x00040000UL -#define DCCP_SOCKET__RECV_MSG                     0x00080000UL -#define DCCP_SOCKET__SEND_MSG                     0x00100000UL -#define DCCP_SOCKET__NAME_BIND                    0x00200000UL -#define DCCP_SOCKET__NODE_BIND                    0x00400000UL -#define DCCP_SOCKET__NAME_CONNECT                 0x00800000UL -#define MEMPROTECT__MMAP_ZERO                     0x00000001UL -#define PEER__RECV                                0x00000001UL -#define KERNEL_SERVICE__USE_AS_OVERRIDE           0x00000001UL -#define KERNEL_SERVICE__CREATE_FILES_AS           0x00000002UL diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index bb1ec801bdf..4677aa519b0 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h @@ -10,26 +10,13 @@  int avc_ss_reset(u32 seqno); -struct av_perm_to_string { -	u16 tclass; -	u32 value; +/* Class/perm mapping support */ +struct security_class_mapping {  	const char *name; +	const char *perms[sizeof(u32) * 8 + 1];  }; -struct av_inherit { -	const char **common_pts; -	u32 common_base; -	u16 tclass; -}; - -struct selinux_class_perm { -	const struct av_perm_to_string *av_perm_to_string; -	u32 av_pts_len; -	u32 cts_len; -	const char **class_to_string; -	const struct av_inherit *av_inherit; -	u32 av_inherit_len; -}; +extern struct security_class_mapping secclass_map[];  #endif /* _SELINUX_AVC_SS_H_ */ diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h deleted file mode 100644 index 7ab9299bfb6..00000000000 --- a/security/selinux/include/class_to_string.h +++ /dev/null @@ -1,80 +0,0 @@ -/* This file is automatically generated.  Do not edit. */ -/* - * Security object class definitions - */ -    S_(NULL) -    S_("security") -    S_("process") -    S_("system") -    S_("capability") -    S_("filesystem") -    S_("file") -    S_("dir") -    S_("fd") -    S_("lnk_file") -    S_("chr_file") -    S_("blk_file") -    S_("sock_file") -    S_("fifo_file") -    S_("socket") -    S_("tcp_socket") -    S_("udp_socket") -    S_("rawip_socket") -    S_("node") -    S_("netif") -    S_("netlink_socket") -    S_("packet_socket") -    S_("key_socket") -    S_("unix_stream_socket") -    S_("unix_dgram_socket") -    S_("sem") -    S_("msg") -    S_("msgq") -    S_("shm") -    S_("ipc") -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_("netlink_route_socket") -    S_("netlink_firewall_socket") -    S_("netlink_tcpdiag_socket") -    S_("netlink_nflog_socket") -    S_("netlink_xfrm_socket") -    S_("netlink_selinux_socket") -    S_("netlink_audit_socket") -    S_("netlink_ip6fw_socket") -    S_("netlink_dnrt_socket") -    S_(NULL) -    S_(NULL) -    S_("association") -    S_("netlink_kobject_uevent_socket") -    S_("appletalk_socket") -    S_("packet") -    S_("key") -    S_(NULL) -    S_("dccp_socket") -    S_("memprotect") -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_("peer") -    S_("capability2") -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_(NULL) -    S_("kernel_service") -    S_("tun_socket") diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h new file mode 100644 index 00000000000..8b32e959bb2 --- /dev/null +++ b/security/selinux/include/classmap.h @@ -0,0 +1,150 @@ +#define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ +    "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" + +#define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ +    "rename", "execute", "swapon", "quotaon", "mounton" + +#define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ +    "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom",  \ +    "sendto", "recv_msg", "send_msg", "name_bind" + +#define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ +	    "write", "associate", "unix_read", "unix_write" + +struct security_class_mapping secclass_map[] = { +	{ "security", +	  { "compute_av", "compute_create", "compute_member", +	    "check_context", "load_policy", "compute_relabel", +	    "compute_user", "setenforce", "setbool", "setsecparam", +	    "setcheckreqprot", NULL } }, +	{ "process", +	  { "fork", "transition", "sigchld", "sigkill", +	    "sigstop", "signull", "signal", "ptrace", "getsched", "setsched", +	    "getsession", "getpgid", "setpgid", "getcap", "setcap", "share", +	    "getattr", "setexec", "setfscreate", "noatsecure", "siginh", +	    "setrlimit", "rlimitinh", "dyntransition", "setcurrent", +	    "execmem", "execstack", "execheap", "setkeycreate", +	    "setsockcreate", NULL } }, +	{ "system", +	  { "ipc_info", "syslog_read", "syslog_mod", +	    "syslog_console", "module_request", NULL } }, +	{ "capability", +	  { "chown", "dac_override", "dac_read_search", +	    "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", +	    "linux_immutable", "net_bind_service", "net_broadcast", +	    "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", +	    "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", +	    "sys_boot", "sys_nice", "sys_resource", "sys_time", +	    "sys_tty_config", "mknod", "lease", "audit_write", +	    "audit_control", "setfcap", NULL } }, +	{ "filesystem", +	  { "mount", "remount", "unmount", "getattr", +	    "relabelfrom", "relabelto", "transition", "associate", "quotamod", +	    "quotaget", NULL } }, +	{ "file", +	  { COMMON_FILE_PERMS, +	    "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, +	{ "dir", +	  { COMMON_FILE_PERMS, "add_name", "remove_name", +	    "reparent", "search", "rmdir", "open", NULL } }, +	{ "fd", { "use", NULL } }, +	{ "lnk_file", +	  { COMMON_FILE_PERMS, NULL } }, +	{ "chr_file", +	  { COMMON_FILE_PERMS, +	    "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, +	{ "blk_file", +	  { COMMON_FILE_PERMS, "open", NULL } }, +	{ "sock_file", +	  { COMMON_FILE_PERMS, "open", NULL } }, +	{ "fifo_file", +	  { COMMON_FILE_PERMS, "open", NULL } }, +	{ "socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "tcp_socket", +	  { COMMON_SOCK_PERMS, +	    "connectto", "newconn", "acceptfrom", "node_bind", "name_connect", +	    NULL } }, +	{ "udp_socket", +	  { COMMON_SOCK_PERMS, +	    "node_bind", NULL } }, +	{ "rawip_socket", +	  { COMMON_SOCK_PERMS, +	    "node_bind", NULL } }, +	{ "node", +	  { "tcp_recv", "tcp_send", "udp_recv", "udp_send", +	    "rawip_recv", "rawip_send", "enforce_dest", +	    "dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } }, +	{ "netif", +	  {  "tcp_recv", "tcp_send", "udp_recv", "udp_send", +	     "rawip_recv", "rawip_send", "dccp_recv", "dccp_send", +	     "ingress", "egress", NULL } }, +	{ "netlink_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "packet_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "key_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "unix_stream_socket", +	  { COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL +	  } }, +	{ "unix_dgram_socket", +	  { COMMON_SOCK_PERMS, NULL +	  } }, +	{ "sem", +	  { COMMON_IPC_PERMS, NULL } }, +	{ "msg", { "send", "receive", NULL } }, +	{ "msgq", +	  { COMMON_IPC_PERMS, "enqueue", NULL } }, +	{ "shm", +	  { COMMON_IPC_PERMS, "lock", NULL } }, +	{ "ipc", +	  { COMMON_IPC_PERMS, NULL } }, +	{ "netlink_route_socket", +	  { COMMON_SOCK_PERMS, +	    "nlmsg_read", "nlmsg_write", NULL } }, +	{ "netlink_firewall_socket", +	  { COMMON_SOCK_PERMS, +	    "nlmsg_read", "nlmsg_write", NULL } }, +	{ "netlink_tcpdiag_socket", +	  { COMMON_SOCK_PERMS, +	    "nlmsg_read", "nlmsg_write", NULL } }, +	{ "netlink_nflog_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "netlink_xfrm_socket", +	  { COMMON_SOCK_PERMS, +	    "nlmsg_read", "nlmsg_write", NULL } }, +	{ "netlink_selinux_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "netlink_audit_socket", +	  { COMMON_SOCK_PERMS, +	    "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv", +	    "nlmsg_tty_audit", NULL } }, +	{ "netlink_ip6fw_socket", +	  { COMMON_SOCK_PERMS, +	    "nlmsg_read", "nlmsg_write", NULL } }, +	{ "netlink_dnrt_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "association", +	  { "sendto", "recvfrom", "setcontext", "polmatch", NULL } }, +	{ "netlink_kobject_uevent_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "appletalk_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ "packet", +	  { "send", "recv", "relabelto", "flow_in", "flow_out", +	    "forward_in", "forward_out", NULL } }, +	{ "key", +	  { "view", "read", "write", "search", "link", "setattr", "create", +	    NULL } }, +	{ "dccp_socket", +	  { COMMON_SOCK_PERMS, +	    "node_bind", "name_connect", NULL } }, +	{ "memprotect", { "mmap_zero", NULL } }, +	{ "peer", { "recv", NULL } }, +	{ "capability2", { "mac_override", "mac_admin", NULL } }, +	{ "kernel_service", { "use_as_override", "create_files_as", NULL } }, +	{ "tun_socket", +	  { COMMON_SOCK_PERMS, NULL } }, +	{ NULL } +  }; diff --git a/security/selinux/include/common_perm_to_string.h b/security/selinux/include/common_perm_to_string.h deleted file mode 100644 index ce5b6e2fe9d..00000000000 --- a/security/selinux/include/common_perm_to_string.h +++ /dev/null @@ -1,58 +0,0 @@ -/* This file is automatically generated.  Do not edit. */ -TB_(common_file_perm_to_string) -    S_("ioctl") -    S_("read") -    S_("write") -    S_("create") -    S_("getattr") -    S_("setattr") -    S_("lock") -    S_("relabelfrom") -    S_("relabelto") -    S_("append") -    S_("unlink") -    S_("link") -    S_("rename") -    S_("execute") -    S_("swapon") -    S_("quotaon") -    S_("mounton") -TE_(common_file_perm_to_string) - -TB_(common_socket_perm_to_string) -    S_("ioctl") -    S_("read") -    S_("write") -    S_("create") -    S_("getattr") -    S_("setattr") -    S_("lock") -    S_("relabelfrom") -    S_("relabelto") -    S_("append") -    S_("bind") -    S_("connect") -    S_("listen") -    S_("accept") -    S_("getopt") -    S_("setopt") -    S_("shutdown") -    S_("recvfrom") -    S_("sendto") -    S_("recv_msg") -    S_("send_msg") -    S_("name_bind") -TE_(common_socket_perm_to_string) - -TB_(common_ipc_perm_to_string) -    S_("create") -    S_("destroy") -    S_("getattr") -    S_("setattr") -    S_("read") -    S_("write") -    S_("associate") -    S_("unix_read") -    S_("unix_write") -TE_(common_ipc_perm_to_string) - diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h deleted file mode 100644 index f248500a1e3..00000000000 --- a/security/selinux/include/flask.h +++ /dev/null @@ -1,91 +0,0 @@ -/* This file is automatically generated.  Do not edit. */ -#ifndef _SELINUX_FLASK_H_ -#define _SELINUX_FLASK_H_ - -/* - * Security object class definitions - */ -#define SECCLASS_SECURITY                                1 -#define SECCLASS_PROCESS                                 2 -#define SECCLASS_SYSTEM                                  3 -#define SECCLASS_CAPABILITY                              4 -#define SECCLASS_FILESYSTEM                              5 -#define SECCLASS_FILE                                    6 -#define SECCLASS_DIR                                     7 -#define SECCLASS_FD                                      8 -#define SECCLASS_LNK_FILE                                9 -#define SECCLASS_CHR_FILE                                10 -#define SECCLASS_BLK_FILE                                11 -#define SECCLASS_SOCK_FILE                               12 -#define SECCLASS_FIFO_FILE                               13 -#define SECCLASS_SOCKET                                  14 -#define SECCLASS_TCP_SOCKET                              15 -#define SECCLASS_UDP_SOCKET                              16 -#define SECCLASS_RAWIP_SOCKET                            17 -#define SECCLASS_NODE                                    18 -#define SECCLASS_NETIF                                   19 -#define SECCLASS_NETLINK_SOCKET                          20 -#define SECCLASS_PACKET_SOCKET                           21 -#define SECCLASS_KEY_SOCKET                              22 -#define SECCLASS_UNIX_STREAM_SOCKET                      23 -#define SECCLASS_UNIX_DGRAM_SOCKET                       24 -#define SECCLASS_SEM                                     25 -#define SECCLASS_MSG                                     26 -#define SECCLASS_MSGQ                                    27 -#define SECCLASS_SHM                                     28 -#define SECCLASS_IPC                                     29 -#define SECCLASS_NETLINK_ROUTE_SOCKET                    43 -#define SECCLASS_NETLINK_FIREWALL_SOCKET                 44 -#define SECCLASS_NETLINK_TCPDIAG_SOCKET                  45 -#define SECCLASS_NETLINK_NFLOG_SOCKET                    46 -#define SECCLASS_NETLINK_XFRM_SOCKET                     47 -#define SECCLASS_NETLINK_SELINUX_SOCKET                  48 -#define SECCLASS_NETLINK_AUDIT_SOCKET                    49 -#define SECCLASS_NETLINK_IP6FW_SOCKET                    50 -#define SECCLASS_NETLINK_DNRT_SOCKET                     51 -#define SECCLASS_ASSOCIATION                             54 -#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET           55 -#define SECCLASS_APPLETALK_SOCKET                        56 -#define SECCLASS_PACKET                                  57 -#define SECCLASS_KEY                                     58 -#define SECCLASS_DCCP_SOCKET                             60 -#define SECCLASS_MEMPROTECT                              61 -#define SECCLASS_PEER                                    68 -#define SECCLASS_CAPABILITY2                             69 -#define SECCLASS_KERNEL_SERVICE                          74 -#define SECCLASS_TUN_SOCKET                              75 - -/* - * Security identifier indices for initial entities - */ -#define SECINITSID_KERNEL                               1 -#define SECINITSID_SECURITY                             2 -#define SECINITSID_UNLABELED                            3 -#define SECINITSID_FS                                   4 -#define SECINITSID_FILE                                 5 -#define SECINITSID_FILE_LABELS                          6 -#define SECINITSID_INIT                                 7 -#define SECINITSID_ANY_SOCKET                           8 -#define SECINITSID_PORT                                 9 -#define SECINITSID_NETIF                                10 -#define SECINITSID_NETMSG                               11 -#define SECINITSID_NODE                                 12 -#define SECINITSID_IGMP_PACKET                          13 -#define SECINITSID_ICMP_SOCKET                          14 -#define SECINITSID_TCP_SOCKET                           15 -#define SECINITSID_SYSCTL_MODPROBE                      16 -#define SECINITSID_SYSCTL                               17 -#define SECINITSID_SYSCTL_FS                            18 -#define SECINITSID_SYSCTL_KERNEL                        19 -#define SECINITSID_SYSCTL_NET                           20 -#define SECINITSID_SYSCTL_NET_UNIX                      21 -#define SECINITSID_SYSCTL_VM                            22 -#define SECINITSID_SYSCTL_DEV                           23 -#define SECINITSID_KMOD                                 24 -#define SECINITSID_POLICY                               25 -#define SECINITSID_SCMP_PACKET                          26 -#define SECINITSID_DEVNULL                              27 - -#define SECINITSID_NUM                                  27 - -#endif diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index ca835795a8b..2553266ad79 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -97,11 +97,18 @@ struct av_decision {  #define AVD_FLAGS_PERMISSIVE	0x0001  int security_compute_av(u32 ssid, u32 tsid, -	u16 tclass, u32 requested, -	struct av_decision *avd); +			u16 tclass, u32 requested, +			struct av_decision *avd); + +int security_compute_av_user(u32 ssid, u32 tsid, +			     u16 tclass, u32 requested, +			     struct av_decision *avd);  int security_transition_sid(u32 ssid, u32 tsid, -	u16 tclass, u32 *out_sid); +			    u16 tclass, u32 *out_sid); + +int security_transition_sid_user(u32 ssid, u32 tsid, +				 u16 tclass, u32 *out_sid);  int security_member_sid(u32 ssid, u32 tsid,  	u16 tclass, u32 *out_sid); diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index b4fc506e7a8..fab36fdf276 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -522,7 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)  	if (length < 0)  		goto out2; -	length = security_compute_av(ssid, tsid, tclass, req, &avd); +	length = security_compute_av_user(ssid, tsid, tclass, req, &avd);  	if (length < 0)  		goto out2; @@ -571,7 +571,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)  	if (length < 0)  		goto out2; -	length = security_transition_sid(ssid, tsid, tclass, &newsid); +	length = security_transition_sid_user(ssid, tsid, tclass, &newsid);  	if (length < 0)  		goto out2; diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile index bad78779b9b..15d4e62917d 100644 --- a/security/selinux/ss/Makefile +++ b/security/selinux/ss/Makefile @@ -2,7 +2,7 @@  # Makefile for building the SELinux security server as part of the kernel tree.  # -EXTRA_CFLAGS += -Isecurity/selinux/include +EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include  obj-y := ss.o  ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index b5407f16c2a..3f2b2706b5b 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -532,7 +532,7 @@ int mls_compute_sid(struct context *scontext,  		}  		/* Fallthrough */  	case AVTAB_CHANGE: -		if (tclass == SECCLASS_PROCESS) +		if (tclass == policydb.process_class)  			/* Use the process MLS attributes. */  			return mls_context_cpy(newcontext, scontext);  		else diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 72e4a54973a..f03667213ea 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -713,7 +713,6 @@ void policydb_destroy(struct policydb *p)  			ebitmap_destroy(&p->type_attr_map[i]);  	}  	kfree(p->type_attr_map); -	kfree(p->undefined_perms);  	ebitmap_destroy(&p->policycaps);  	ebitmap_destroy(&p->permissive_map); @@ -1640,6 +1639,40 @@ static int policydb_bounds_sanity_check(struct policydb *p)  extern int ss_initialized; +u16 string_to_security_class(struct policydb *p, const char *name) +{ +	struct class_datum *cladatum; + +	cladatum = hashtab_search(p->p_classes.table, name); +	if (!cladatum) +		return 0; + +	return cladatum->value; +} + +u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) +{ +	struct class_datum *cladatum; +	struct perm_datum *perdatum = NULL; +	struct common_datum *comdatum; + +	if (!tclass || tclass > p->p_classes.nprim) +		return 0; + +	cladatum = p->class_val_to_struct[tclass-1]; +	comdatum = cladatum->comdatum; +	if (comdatum) +		perdatum = hashtab_search(comdatum->permissions.table, +					  name); +	if (!perdatum) +		perdatum = hashtab_search(cladatum->permissions.table, +					  name); +	if (!perdatum) +		return 0; + +	return 1U << (perdatum->value-1); +} +  /*   * Read the configuration data from a policy database binary   * representation file into a policy database structure. @@ -1861,6 +1894,16 @@ int policydb_read(struct policydb *p, void *fp)  	if (rc)  		goto bad; +	p->process_class = string_to_security_class(p, "process"); +	if (!p->process_class) +		goto bad; +	p->process_trans_perms = string_to_av_perm(p, p->process_class, +						   "transition"); +	p->process_trans_perms |= string_to_av_perm(p, p->process_class, +						    "dyntransition"); +	if (!p->process_trans_perms) +		goto bad; +  	for (i = 0; i < info->ocon_num; i++) {  		rc = next_entry(buf, fp, sizeof(u32));  		if (rc < 0) @@ -2101,7 +2144,7 @@ int policydb_read(struct policydb *p, void *fp)  					goto bad;  				rt->target_class = le32_to_cpu(buf[0]);  			} else -				rt->target_class = SECCLASS_PROCESS; +				rt->target_class = p->process_class;  			if (!policydb_type_isvalid(p, rt->source_type) ||  			    !policydb_type_isvalid(p, rt->target_type) ||  			    !policydb_class_isvalid(p, rt->target_class)) { diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 55152d498b5..cdcc5700946 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -254,7 +254,9 @@ struct policydb {  	unsigned int reject_unknown : 1;  	unsigned int allow_unknown : 1; -	u32 *undefined_perms; + +	u16 process_class; +	u32 process_trans_perms;  };  extern void policydb_destroy(struct policydb *p); @@ -295,5 +297,8 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)  	return 0;  } +extern u16 string_to_security_class(struct policydb *p, const char *name); +extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name); +  #endif	/* _SS_POLICYDB_H_ */ diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ff17820d35e..d6bb20cbad6 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -65,16 +65,10 @@  #include "audit.h"  extern void selnl_notify_policyload(u32 seqno); -unsigned int policydb_loaded_version;  int selinux_policycap_netpeer;  int selinux_policycap_openperm; -/* - * This is declared in avc.c - */ -extern const struct selinux_class_perm selinux_class_perm; -  static DEFINE_RWLOCK(policy_rwlock);  static struct sidtab sidtab; @@ -98,6 +92,165 @@ static int context_struct_compute_av(struct context *scontext,  				     u16 tclass,  				     u32 requested,  				     struct av_decision *avd); + +struct selinux_mapping { +	u16 value; /* policy value */ +	unsigned num_perms; +	u32 perms[sizeof(u32) * 8]; +}; + +static struct selinux_mapping *current_mapping; +static u16 current_mapping_size; + +static int selinux_set_mapping(struct policydb *pol, +			       struct security_class_mapping *map, +			       struct selinux_mapping **out_map_p, +			       u16 *out_map_size) +{ +	struct selinux_mapping *out_map = NULL; +	size_t size = sizeof(struct selinux_mapping); +	u16 i, j; +	unsigned k; +	bool print_unknown_handle = false; + +	/* Find number of classes in the input mapping */ +	if (!map) +		return -EINVAL; +	i = 0; +	while (map[i].name) +		i++; + +	/* Allocate space for the class records, plus one for class zero */ +	out_map = kcalloc(++i, size, GFP_ATOMIC); +	if (!out_map) +		return -ENOMEM; + +	/* Store the raw class and permission values */ +	j = 0; +	while (map[j].name) { +		struct security_class_mapping *p_in = map + (j++); +		struct selinux_mapping *p_out = out_map + j; + +		/* An empty class string skips ahead */ +		if (!strcmp(p_in->name, "")) { +			p_out->num_perms = 0; +			continue; +		} + +		p_out->value = string_to_security_class(pol, p_in->name); +		if (!p_out->value) { +			printk(KERN_INFO +			       "SELinux:  Class %s not defined in policy.\n", +			       p_in->name); +			if (pol->reject_unknown) +				goto err; +			p_out->num_perms = 0; +			print_unknown_handle = true; +			continue; +		} + +		k = 0; +		while (p_in->perms && p_in->perms[k]) { +			/* An empty permission string skips ahead */ +			if (!*p_in->perms[k]) { +				k++; +				continue; +			} +			p_out->perms[k] = string_to_av_perm(pol, p_out->value, +							    p_in->perms[k]); +			if (!p_out->perms[k]) { +				printk(KERN_INFO +				       "SELinux:  Permission %s in class %s not defined in policy.\n", +				       p_in->perms[k], p_in->name); +				if (pol->reject_unknown) +					goto err; +				print_unknown_handle = true; +			} + +			k++; +		} +		p_out->num_perms = k; +	} + +	if (print_unknown_handle) +		printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", +		       pol->allow_unknown ? "allowed" : "denied"); + +	*out_map_p = out_map; +	*out_map_size = i; +	return 0; +err: +	kfree(out_map); +	return -EINVAL; +} + +/* + * Get real, policy values from mapped values + */ + +static u16 unmap_class(u16 tclass) +{ +	if (tclass < current_mapping_size) +		return current_mapping[tclass].value; + +	return tclass; +} + +static u32 unmap_perm(u16 tclass, u32 tperm) +{ +	if (tclass < current_mapping_size) { +		unsigned i; +		u32 kperm = 0; + +		for (i = 0; i < current_mapping[tclass].num_perms; i++) +			if (tperm & (1<<i)) { +				kperm |= current_mapping[tclass].perms[i]; +				tperm &= ~(1<<i); +			} +		return kperm; +	} + +	return tperm; +} + +static void map_decision(u16 tclass, struct av_decision *avd, +			 int allow_unknown) +{ +	if (tclass < current_mapping_size) { +		unsigned i, n = current_mapping[tclass].num_perms; +		u32 result; + +		for (i = 0, result = 0; i < n; i++) { +			if (avd->allowed & current_mapping[tclass].perms[i]) +				result |= 1<<i; +			if (allow_unknown && !current_mapping[tclass].perms[i]) +				result |= 1<<i; +		} +		avd->allowed = result; + +		for (i = 0, result = 0; i < n; i++) +			if (avd->auditallow & current_mapping[tclass].perms[i]) +				result |= 1<<i; +		avd->auditallow = result; + +		for (i = 0, result = 0; i < n; i++) { +			if (avd->auditdeny & current_mapping[tclass].perms[i]) +				result |= 1<<i; +			if (!allow_unknown && !current_mapping[tclass].perms[i]) +				result |= 1<<i; +		} +		/* +		 * In case the kernel has a bug and requests a permission +		 * between num_perms and the maximum permission number, we +		 * should audit that denial +		 */ +		for (; i < (sizeof(u32)*8); i++) +			result |= 1<<i; +		avd->auditdeny = result; +	} +} + +  /*   * Return the boolean value of a constraint expression   * when it is applied to the specified source and target @@ -467,21 +620,9 @@ static int context_struct_compute_av(struct context *scontext,  	struct class_datum *tclass_datum;  	struct ebitmap *sattr, *tattr;  	struct ebitmap_node *snode, *tnode; -	const struct selinux_class_perm *kdefs = &selinux_class_perm;  	unsigned int i, j;  	/* -	 * Remap extended Netlink classes for old policy versions. -	 * Do this here rather than socket_type_to_security_class() -	 * in case a newer policy version is loaded, allowing sockets -	 * to remain in the correct class. -	 */ -	if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) -		if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && -		    tclass <= SECCLASS_NETLINK_DNRT_SOCKET) -			tclass = SECCLASS_NETLINK_SOCKET; - -	/*  	 * Initialize the access vectors to the default values.  	 */  	avd->allowed = 0; @@ -490,33 +631,11 @@ static int context_struct_compute_av(struct context *scontext,  	avd->seqno = latest_granting;  	avd->flags = 0; -	/* -	 * Check for all the invalid cases. -	 * - tclass 0 -	 * - tclass > policy and > kernel -	 * - tclass > policy but is a userspace class -	 * - tclass > policy but we do not allow unknowns -	 */ -	if (unlikely(!tclass)) -		goto inval_class; -	if (unlikely(tclass > policydb.p_classes.nprim)) -		if (tclass > kdefs->cts_len || -		    !kdefs->class_to_string[tclass] || -		    !policydb.allow_unknown) -			goto inval_class; - -	/* -	 * Kernel class and we allow unknown so pad the allow decision -	 * the pad will be all 1 for unknown classes. -	 */ -	if (tclass <= kdefs->cts_len && policydb.allow_unknown) -		avd->allowed = policydb.undefined_perms[tclass - 1]; - -	/* -	 * Not in policy. Since decision is completed (all 1 or all 0) return. -	 */ -	if (unlikely(tclass > policydb.p_classes.nprim)) -		return 0; +	if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { +		if (printk_ratelimit()) +			printk(KERN_WARNING "SELinux:  Invalid class %hu\n", tclass); +		return -EINVAL; +	}  	tclass_datum = policydb.class_val_to_struct[tclass - 1]; @@ -568,8 +687,8 @@ static int context_struct_compute_av(struct context *scontext,  	 * role is changing, then check the (current_role, new_role)  	 * pair.  	 */ -	if (tclass == SECCLASS_PROCESS && -	    (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && +	if (tclass == policydb.process_class && +	    (avd->allowed & policydb.process_trans_perms) &&  	    scontext->role != tcontext->role) {  		for (ra = policydb.role_allow; ra; ra = ra->next) {  			if (scontext->role == ra->role && @@ -577,8 +696,7 @@ static int context_struct_compute_av(struct context *scontext,  				break;  		}  		if (!ra) -			avd->allowed &= ~(PROCESS__TRANSITION | -					  PROCESS__DYNTRANSITION); +			avd->allowed &= ~policydb.process_trans_perms;  	}  	/* @@ -590,21 +708,6 @@ static int context_struct_compute_av(struct context *scontext,  				 tclass, requested, avd);  	return 0; - -inval_class: -	if (!tclass || tclass > kdefs->cts_len || -	    !kdefs->class_to_string[tclass]) { -		if (printk_ratelimit()) -			printk(KERN_ERR "SELinux: %s:  unrecognized class %d\n", -			       __func__, tclass); -		return -EINVAL; -	} - -	/* -	 * Known to the kernel, but not to the policy. -	 * Handle as a denial (allowed is 0). -	 */ -	return 0;  }  static int security_validtrans_handle_fail(struct context *ocontext, @@ -636,13 +739,14 @@ out:  }  int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, -				 u16 tclass) +				 u16 orig_tclass)  {  	struct context *ocontext;  	struct context *ncontext;  	struct context *tcontext;  	struct class_datum *tclass_datum;  	struct constraint_node *constraint; +	u16 tclass;  	int rc = 0;  	if (!ss_initialized) @@ -650,16 +754,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,  	read_lock(&policy_rwlock); -	/* -	 * Remap extended Netlink classes for old policy versions. -	 * Do this here rather than socket_type_to_security_class() -	 * in case a newer policy version is loaded, allowing sockets -	 * to remain in the correct class. -	 */ -	if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) -		if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && -		    tclass <= SECCLASS_NETLINK_DNRT_SOCKET) -			tclass = SECCLASS_NETLINK_SOCKET; +	tclass = unmap_class(orig_tclass);  	if (!tclass || tclass > policydb.p_classes.nprim) {  		printk(KERN_ERR "SELinux: %s:  unrecognized class %d\n", @@ -792,6 +887,38 @@ out:  } +static int security_compute_av_core(u32 ssid, +				    u32 tsid, +				    u16 tclass, +				    u32 requested, +				    struct av_decision *avd) +{ +	struct context *scontext = NULL, *tcontext = NULL; +	int rc = 0; + +	scontext = sidtab_search(&sidtab, ssid); +	if (!scontext) { +		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n", +		       __func__, ssid); +		return -EINVAL; +	} +	tcontext = sidtab_search(&sidtab, tsid); +	if (!tcontext) { +		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n", +		       __func__, tsid); +		return -EINVAL; +	} + +	rc = context_struct_compute_av(scontext, tcontext, tclass, +				       requested, avd); + +	/* permissive domain? */ +	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) +		avd->flags |= AVD_FLAGS_PERMISSIVE; + +	return rc; +} +  /**   * security_compute_av - Compute access vector decisions.   * @ssid: source security identifier @@ -807,12 +934,49 @@ out:   */  int security_compute_av(u32 ssid,  			u32 tsid, -			u16 tclass, -			u32 requested, +			u16 orig_tclass, +			u32 orig_requested,  			struct av_decision *avd)  { -	struct context *scontext = NULL, *tcontext = NULL; -	int rc = 0; +	u16 tclass; +	u32 requested; +	int rc; + +	read_lock(&policy_rwlock); + +	if (!ss_initialized) +		goto allow; + +	requested = unmap_perm(orig_tclass, orig_requested); +	tclass = unmap_class(orig_tclass); +	if (unlikely(orig_tclass && !tclass)) { +		if (policydb.allow_unknown) +			goto allow; +		rc = -EINVAL; +		goto out; +	} +	rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); +	map_decision(orig_tclass, avd, policydb.allow_unknown); +out: +	read_unlock(&policy_rwlock); +	return rc; +allow: +	avd->allowed = 0xffffffff; +	avd->auditallow = 0; +	avd->auditdeny = 0xffffffff; +	avd->seqno = latest_granting; +	avd->flags = 0; +	rc = 0; +	goto out; +} + +int security_compute_av_user(u32 ssid, +			     u32 tsid, +			     u16 tclass, +			     u32 requested, +			     struct av_decision *avd) +{ +	int rc;  	if (!ss_initialized) {  		avd->allowed = 0xffffffff; @@ -823,29 +987,7 @@ int security_compute_av(u32 ssid,  	}  	read_lock(&policy_rwlock); - -	scontext = sidtab_search(&sidtab, ssid); -	if (!scontext) { -		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n", -		       __func__, ssid); -		rc = -EINVAL; -		goto out; -	} -	tcontext = sidtab_search(&sidtab, tsid); -	if (!tcontext) { -		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n", -		       __func__, tsid); -		rc = -EINVAL; -		goto out; -	} - -	rc = context_struct_compute_av(scontext, tcontext, tclass, -				       requested, avd); - -	/* permissive domain? */ -	if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) -	    avd->flags |= AVD_FLAGS_PERMISSIVE; -out: +	rc = security_compute_av_core(ssid, tsid, tclass, requested, avd);  	read_unlock(&policy_rwlock);  	return rc;  } @@ -1204,20 +1346,22 @@ out:  static int security_compute_sid(u32 ssid,  				u32 tsid, -				u16 tclass, +				u16 orig_tclass,  				u32 specified, -				u32 *out_sid) +				u32 *out_sid, +				bool kern)  {  	struct context *scontext = NULL, *tcontext = NULL, newcontext;  	struct role_trans *roletr = NULL;  	struct avtab_key avkey;  	struct avtab_datum *avdatum;  	struct avtab_node *node; +	u16 tclass;  	int rc = 0;  	if (!ss_initialized) { -		switch (tclass) { -		case SECCLASS_PROCESS: +		switch (orig_tclass) { +		case SECCLASS_PROCESS: /* kernel value */  			*out_sid = ssid;  			break;  		default: @@ -1231,6 +1375,11 @@ static int security_compute_sid(u32 ssid,  	read_lock(&policy_rwlock); +	if (kern) +		tclass = unmap_class(orig_tclass); +	else +		tclass = orig_tclass; +  	scontext = sidtab_search(&sidtab, ssid);  	if (!scontext) {  		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n", @@ -1260,13 +1409,11 @@ static int security_compute_sid(u32 ssid,  	}  	/* Set the role and type to default values. */ -	switch (tclass) { -	case SECCLASS_PROCESS: +	if (tclass == policydb.process_class) {  		/* Use the current role and type of process. */  		newcontext.role = scontext->role;  		newcontext.type = scontext->type; -		break; -	default: +	} else {  		/* Use the well-defined object role. */  		newcontext.role = OBJECT_R_VAL;  		/* Use the type of the related object. */ @@ -1297,8 +1444,7 @@ static int security_compute_sid(u32 ssid,  	}  	/* Check for class-specific changes. */ -	switch (tclass) { -	case SECCLASS_PROCESS: +	if  (tclass == policydb.process_class) {  		if (specified & AVTAB_TRANSITION) {  			/* Look for a role transition rule. */  			for (roletr = policydb.role_tr; roletr; @@ -1311,9 +1457,6 @@ static int security_compute_sid(u32 ssid,  				}  			}  		} -		break; -	default: -		break;  	}  	/* Set the MLS attributes. @@ -1358,7 +1501,17 @@ int security_transition_sid(u32 ssid,  			    u16 tclass,  			    u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); +	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, +				    out_sid, true); +} + +int security_transition_sid_user(u32 ssid, +				 u32 tsid, +				 u16 tclass, +				 u32 *out_sid) +{ +	return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, +				    out_sid, false);  }  /** @@ -1379,7 +1532,8 @@ int security_member_sid(u32 ssid,  			u16 tclass,  			u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); +	return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, +				    false);  }  /** @@ -1400,144 +1554,8 @@ int security_change_sid(u32 ssid,  			u16 tclass,  			u32 *out_sid)  { -	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); -} - -/* - * Verify that each kernel class that is defined in the - * policy is correct - */ -static int validate_classes(struct policydb *p) -{ -	int i, j; -	struct class_datum *cladatum; -	struct perm_datum *perdatum; -	u32 nprim, tmp, common_pts_len, perm_val, pol_val; -	u16 class_val; -	const struct selinux_class_perm *kdefs = &selinux_class_perm; -	const char *def_class, *def_perm, *pol_class; -	struct symtab *perms; -	bool print_unknown_handle = 0; - -	if (p->allow_unknown) { -		u32 num_classes = kdefs->cts_len; -		p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); -		if (!p->undefined_perms) -			return -ENOMEM; -	} - -	for (i = 1; i < kdefs->cts_len; i++) { -		def_class = kdefs->class_to_string[i]; -		if (!def_class) -			continue; -		if (i > p->p_classes.nprim) { -			printk(KERN_INFO -			       "SELinux:  class %s not defined in policy\n", -			       def_class); -			if (p->reject_unknown) -				return -EINVAL; -			if (p->allow_unknown) -				p->undefined_perms[i-1] = ~0U; -			print_unknown_handle = 1; -			continue; -		} -		pol_class = p->p_class_val_to_name[i-1]; -		if (strcmp(pol_class, def_class)) { -			printk(KERN_ERR -			       "SELinux:  class %d is incorrect, found %s but should be %s\n", -			       i, pol_class, def_class); -			return -EINVAL; -		} -	} -	for (i = 0; i < kdefs->av_pts_len; i++) { -		class_val = kdefs->av_perm_to_string[i].tclass; -		perm_val = kdefs->av_perm_to_string[i].value; -		def_perm = kdefs->av_perm_to_string[i].name; -		if (class_val > p->p_classes.nprim) -			continue; -		pol_class = p->p_class_val_to_name[class_val-1]; -		cladatum = hashtab_search(p->p_classes.table, pol_class); -		BUG_ON(!cladatum); -		perms = &cladatum->permissions; -		nprim = 1 << (perms->nprim - 1); -		if (perm_val > nprim) { -			printk(KERN_INFO -			       "SELinux:  permission %s in class %s not defined in policy\n", -			       def_perm, pol_class); -			if (p->reject_unknown) -				return -EINVAL; -			if (p->allow_unknown) -				p->undefined_perms[class_val-1] |= perm_val; -			print_unknown_handle = 1; -			continue; -		} -		perdatum = hashtab_search(perms->table, def_perm); -		if (perdatum == NULL) { -			printk(KERN_ERR -			       "SELinux:  permission %s in class %s not found in policy, bad policy\n", -			       def_perm, pol_class); -			return -EINVAL; -		} -		pol_val = 1 << (perdatum->value - 1); -		if (pol_val != perm_val) { -			printk(KERN_ERR -			       "SELinux:  permission %s in class %s has incorrect value\n", -			       def_perm, pol_class); -			return -EINVAL; -		} -	} -	for (i = 0; i < kdefs->av_inherit_len; i++) { -		class_val = kdefs->av_inherit[i].tclass; -		if (class_val > p->p_classes.nprim) -			continue; -		pol_class = p->p_class_val_to_name[class_val-1]; -		cladatum = hashtab_search(p->p_classes.table, pol_class); -		BUG_ON(!cladatum); -		if (!cladatum->comdatum) { -			printk(KERN_ERR -			       "SELinux:  class %s should have an inherits clause but does not\n", -			       pol_class); -			return -EINVAL; -		} -		tmp = kdefs->av_inherit[i].common_base; -		common_pts_len = 0; -		while (!(tmp & 0x01)) { -			common_pts_len++; -			tmp >>= 1; -		} -		perms = &cladatum->comdatum->permissions; -		for (j = 0; j < common_pts_len; j++) { -			def_perm = kdefs->av_inherit[i].common_pts[j]; -			if (j >= perms->nprim) { -				printk(KERN_INFO -				       "SELinux:  permission %s in class %s not defined in policy\n", -				       def_perm, pol_class); -				if (p->reject_unknown) -					return -EINVAL; -				if (p->allow_unknown) -					p->undefined_perms[class_val-1] |= (1 << j); -				print_unknown_handle = 1; -				continue; -			} -			perdatum = hashtab_search(perms->table, def_perm); -			if (perdatum == NULL) { -				printk(KERN_ERR -				       "SELinux:  permission %s in class %s not found in policy, bad policy\n", -				       def_perm, pol_class); -				return -EINVAL; -			} -			if (perdatum->value != j + 1) { -				printk(KERN_ERR -				       "SELinux:  permission %s in class %s has incorrect value\n", -				       def_perm, pol_class); -				return -EINVAL; -			} -		} -	} -	if (print_unknown_handle) -		printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", -			(security_get_allow_unknown() ? "allowed" : "denied")); -	return 0; +	return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, +				    false);  }  /* Clone the SID into the new SID table. */ @@ -1710,8 +1728,10 @@ int security_load_policy(void *data, size_t len)  {  	struct policydb oldpolicydb, newpolicydb;  	struct sidtab oldsidtab, newsidtab; +	struct selinux_mapping *oldmap, *map = NULL;  	struct convert_context_args args;  	u32 seqno; +	u16 map_size;  	int rc = 0;  	struct policy_file file = { data, len }, *fp = &file; @@ -1721,22 +1741,19 @@ int security_load_policy(void *data, size_t len)  			avtab_cache_destroy();  			return -EINVAL;  		} -		if (policydb_load_isids(&policydb, &sidtab)) { +		if (selinux_set_mapping(&policydb, secclass_map, +					¤t_mapping, +					¤t_mapping_size)) {  			policydb_destroy(&policydb);  			avtab_cache_destroy();  			return -EINVAL;  		} -		/* Verify that the kernel defined classes are correct. */ -		if (validate_classes(&policydb)) { -			printk(KERN_ERR -			       "SELinux:  the definition of a class is incorrect\n"); -			sidtab_destroy(&sidtab); +		if (policydb_load_isids(&policydb, &sidtab)) {  			policydb_destroy(&policydb);  			avtab_cache_destroy();  			return -EINVAL;  		}  		security_load_policycaps(); -		policydb_loaded_version = policydb.policyvers;  		ss_initialized = 1;  		seqno = ++latest_granting;  		selinux_complete_init(); @@ -1759,13 +1776,9 @@ int security_load_policy(void *data, size_t len)  		return -ENOMEM;  	} -	/* Verify that the kernel defined classes are correct. */ -	if (validate_classes(&newpolicydb)) { -		printk(KERN_ERR -		       "SELinux:  the definition of a class is incorrect\n"); -		rc = -EINVAL; +	if (selinux_set_mapping(&newpolicydb, secclass_map, +				&map, &map_size))  		goto err; -	}  	rc = security_preserve_bools(&newpolicydb);  	if (rc) { @@ -1799,13 +1812,16 @@ int security_load_policy(void *data, size_t len)  	memcpy(&policydb, &newpolicydb, sizeof policydb);  	sidtab_set(&sidtab, &newsidtab);  	security_load_policycaps(); +	oldmap = current_mapping; +	current_mapping = map; +	current_mapping_size = map_size;  	seqno = ++latest_granting; -	policydb_loaded_version = policydb.policyvers;  	write_unlock_irq(&policy_rwlock);  	/* Free the old policydb and SID table. */  	policydb_destroy(&oldpolicydb);  	sidtab_destroy(&oldsidtab); +	kfree(oldmap);  	avc_ss_reset(seqno);  	selnl_notify_policyload(seqno); @@ -1815,6 +1831,7 @@ int security_load_policy(void *data, size_t len)  	return 0;  err: +	kfree(map);  	sidtab_destroy(&newsidtab);  	policydb_destroy(&newpolicydb);  	return rc; @@ -2091,7 +2108,7 @@ out_unlock:  	}  	for (i = 0, j = 0; i < mynel; i++) {  		rc = avc_has_perm_noaudit(fromsid, mysids[i], -					  SECCLASS_PROCESS, +					  SECCLASS_PROCESS, /* kernel value */  					  PROCESS__TRANSITION, AVC_STRICT,  					  NULL);  		if (!rc) @@ -2119,10 +2136,11 @@ out:   */  int security_genfs_sid(const char *fstype,  		       char *path, -		       u16 sclass, +		       u16 orig_sclass,  		       u32 *sid)  {  	int len; +	u16 sclass;  	struct genfs *genfs;  	struct ocontext *c;  	int rc = 0, cmp = 0; @@ -2132,6 +2150,8 @@ int security_genfs_sid(const char *fstype,  	read_lock(&policy_rwlock); +	sclass = unmap_class(orig_sclass); +  	for (genfs = policydb.genfs; genfs; genfs = genfs->next) {  		cmp = strcmp(fstype, genfs->fstype);  		if (cmp <= 0) diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 3c8bd8ee0b9..e0d0354008b 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -187,6 +187,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,  			    const s8 pattern_type, const s8 end_type,  			    const char *function)  { +	const char *const start = filename; +	bool in_repetition = false;  	bool contains_pattern = false;  	unsigned char c;  	unsigned char d; @@ -212,9 +214,13 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,  		if (c == '/')  			goto out;  	} -	while ((c = *filename++) != '\0') { +	while (1) { +		c = *filename++; +		if (!c) +			break;  		if (c == '\\') { -			switch ((c = *filename++)) { +			c = *filename++; +			switch (c) {  			case '\\':  /* "\\" */  				continue;  			case '$':   /* "\$" */ @@ -231,6 +237,22 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,  					break; /* Must not contain pattern */  				contains_pattern = true;  				continue; +			case '{':   /* "/\{" */ +				if (filename - 3 < start || +				    *(filename - 3) != '/') +					break; +				if (pattern_type == -1) +					break; /* Must not contain pattern */ +				contains_pattern = true; +				in_repetition = true; +				continue; +			case '}':   /* "\}/" */ +				if (*filename != '/') +					break; +				if (!in_repetition) +					break; +				in_repetition = false; +				continue;  			case '0':   /* "\ooo" */  			case '1':  			case '2': @@ -246,6 +268,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,  					continue; /* pattern is not \000 */  			}  			goto out; +		} else if (in_repetition && c == '/') { +			goto out;  		} else if (tomoyo_is_invalid(c)) {  			goto out;  		} @@ -254,6 +278,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,  		if (!contains_pattern)  			goto out;  	} +	if (in_repetition) +		goto out;  	return true;   out:  	printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function, @@ -360,33 +386,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)  }  /** - * tomoyo_path_depth - Evaluate the number of '/' in a string. - * - * @pathname: The string to evaluate. - * - * Returns path depth of the string. - * - * I score 2 for each of the '/' in the @pathname - * and score 1 if the @pathname ends with '/'. - */ -static int tomoyo_path_depth(const char *pathname) -{ -	int i = 0; - -	if (pathname) { -		const char *ep = pathname + strlen(pathname); -		if (pathname < ep--) { -			if (*ep != '/') -				i++; -			while (pathname <= ep) -				if (*ep-- == '/') -					i += 2; -		} -	} -	return i; -} - -/**   * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.   *   * @filename: The string to evaluate. @@ -444,11 +443,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)  	ptr->is_dir = len && (name[len - 1] == '/');  	ptr->is_patterned = (ptr->const_len < len);  	ptr->hash = full_name_hash(name, len); -	ptr->depth = tomoyo_path_depth(name);  }  /** - * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character + * tomoyo_file_matches_pattern2 - Pattern matching without '/' character   * and "\-" pattern.   *   * @filename:     The start of string to check. @@ -458,10 +456,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)   *   * Returns true if @filename matches @pattern, false otherwise.   */ -static bool tomoyo_file_matches_to_pattern2(const char *filename, -					    const char *filename_end, -					    const char *pattern, -					    const char *pattern_end) +static bool tomoyo_file_matches_pattern2(const char *filename, +					 const char *filename_end, +					 const char *pattern, +					 const char *pattern_end)  {  	while (filename < filename_end && pattern < pattern_end) {  		char c; @@ -519,7 +517,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,  		case '*':  		case '@':  			for (i = 0; i <= filename_end - filename; i++) { -				if (tomoyo_file_matches_to_pattern2( +				if (tomoyo_file_matches_pattern2(  						    filename + i, filename_end,  						    pattern + 1, pattern_end))  					return true; @@ -550,7 +548,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,  					j++;  			}  			for (i = 1; i <= j; i++) { -				if (tomoyo_file_matches_to_pattern2( +				if (tomoyo_file_matches_pattern2(  						    filename + i, filename_end,  						    pattern + 1, pattern_end))  					return true; @@ -567,7 +565,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,  }  /** - * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character. + * tomoyo_file_matches_pattern - Pattern matching without without '/' character.   *   * @filename:     The start of string to check.   * @filename_end: The end of string to check. @@ -576,7 +574,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename,   *   * Returns true if @filename matches @pattern, false otherwise.   */ -static bool tomoyo_file_matches_to_pattern(const char *filename, +static bool tomoyo_file_matches_pattern(const char *filename,  					   const char *filename_end,  					   const char *pattern,  					   const char *pattern_end) @@ -589,10 +587,10 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,  		/* Split at "\-" pattern. */  		if (*pattern++ != '\\' || *pattern++ != '-')  			continue; -		result = tomoyo_file_matches_to_pattern2(filename, -							 filename_end, -							 pattern_start, -							 pattern - 2); +		result = tomoyo_file_matches_pattern2(filename, +						      filename_end, +						      pattern_start, +						      pattern - 2);  		if (first)  			result = !result;  		if (result) @@ -600,13 +598,79 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,  		first = false;  		pattern_start = pattern;  	} -	result = tomoyo_file_matches_to_pattern2(filename, filename_end, -						 pattern_start, pattern_end); +	result = tomoyo_file_matches_pattern2(filename, filename_end, +					      pattern_start, pattern_end);  	return first ? result : !result;  }  /** + * tomoyo_path_matches_pattern2 - Do pathname pattern matching. + * + * @f: The start of string to check. + * @p: The start of pattern to compare. + * + * Returns true if @f matches @p, false otherwise. + */ +static bool tomoyo_path_matches_pattern2(const char *f, const char *p) +{ +	const char *f_delimiter; +	const char *p_delimiter; + +	while (*f && *p) { +		f_delimiter = strchr(f, '/'); +		if (!f_delimiter) +			f_delimiter = f + strlen(f); +		p_delimiter = strchr(p, '/'); +		if (!p_delimiter) +			p_delimiter = p + strlen(p); +		if (*p == '\\' && *(p + 1) == '{') +			goto recursive; +		if (!tomoyo_file_matches_pattern(f, f_delimiter, p, +						 p_delimiter)) +			return false; +		f = f_delimiter; +		if (*f) +			f++; +		p = p_delimiter; +		if (*p) +			p++; +	} +	/* Ignore trailing "\*" and "\@" in @pattern. */ +	while (*p == '\\' && +	       (*(p + 1) == '*' || *(p + 1) == '@')) +		p += 2; +	return !*f && !*p; + recursive: +	/* +	 * The "\{" pattern is permitted only after '/' character. +	 * This guarantees that below "*(p - 1)" is safe. +	 * Also, the "\}" pattern is permitted only before '/' character +	 * so that "\{" + "\}" pair will not break the "\-" operator. +	 */ +	if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || +	    *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\') +		return false; /* Bad pattern. */ +	do { +		/* Compare current component with pattern. */ +		if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2, +						 p_delimiter - 2)) +			break; +		/* Proceed to next component. */ +		f = f_delimiter; +		if (!*f) +			break; +		f++; +		/* Continue comparison. */ +		if (tomoyo_path_matches_pattern2(f, p_delimiter + 1)) +			return true; +		f_delimiter = strchr(f, '/'); +	} while (f_delimiter); +	return false; /* Not matched. */ +} + +/**   * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. + *   * @filename: The filename to check.   * @pattern:  The pattern to compare.   * @@ -615,24 +679,24 @@ static bool tomoyo_file_matches_to_pattern(const char *filename,   * The following patterns are available.   *   \\     \ itself.   *   \ooo   Octal representation of a byte. - *   \*     More than or equals to 0 character other than '/'. - *   \@     More than or equals to 0 character other than '/' or '.'. + *   \*     Zero or more repetitions of characters other than '/'. + *   \@     Zero or more repetitions of characters other than '/' or '.'.   *   \?     1 byte character other than '/'. - *   \$     More than or equals to 1 decimal digit. + *   \$     One or more repetitions of decimal digits.   *   \+     1 decimal digit. - *   \X     More than or equals to 1 hexadecimal digit. + *   \X     One or more repetitions of hexadecimal digits.   *   \x     1 hexadecimal digit. - *   \A     More than or equals to 1 alphabet character. + *   \A     One or more repetitions of alphabet characters.   *   \a     1 alphabet character. + *   *   \-     Subtraction operator. + * + *   /\{dir\}/   '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ + *               /dir/dir/dir/ ).   */  bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,  				 const struct tomoyo_path_info *pattern)  { -	/* -	  if (!filename || !pattern) -	  return false; -	*/  	const char *f = filename->name;  	const char *p = pattern->name;  	const int len = pattern->const_len; @@ -640,37 +704,15 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,  	/* If @pattern doesn't contain pattern, I can use strcmp(). */  	if (!pattern->is_patterned)  		return !tomoyo_pathcmp(filename, pattern); -	/* Dont compare if the number of '/' differs. */ -	if (filename->depth != pattern->depth) +	/* Don't compare directory and non-directory. */ +	if (filename->is_dir != pattern->is_dir)  		return false;  	/* Compare the initial length without patterns. */  	if (strncmp(f, p, len))  		return false;  	f += len;  	p += len; -	/* Main loop. Compare each directory component. */ -	while (*f && *p) { -		const char *f_delimiter = strchr(f, '/'); -		const char *p_delimiter = strchr(p, '/'); -		if (!f_delimiter) -			f_delimiter = f + strlen(f); -		if (!p_delimiter) -			p_delimiter = p + strlen(p); -		if (!tomoyo_file_matches_to_pattern(f, f_delimiter, -						    p, p_delimiter)) -			return false; -		f = f_delimiter; -		if (*f) -			f++; -		p = p_delimiter; -		if (*p) -			p++; -	} -	/* Ignore trailing "\*" and "\@" in @pattern. */ -	while (*p == '\\' && -	       (*(p + 1) == '*' || *(p + 1) == '@')) -		p += 2; -	return !*f && !*p; +	return tomoyo_path_matches_pattern2(f, p);  }  /** diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 31df541911f..92169d29b2d 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -56,9 +56,6 @@ struct tomoyo_page_buffer {   * (5) "is_patterned" is a bool which is true if "name" contains wildcard   *     characters, false otherwise. This allows TOMOYO to use "hash" and   *     strcmp() for string comparison if "is_patterned" is false. - * (6) "depth" is calculated using the number of "/" characters in "name". - *     This allows TOMOYO to avoid comparing two pathnames which never match - *     (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$").   */  struct tomoyo_path_info {  	const char *name; @@ -66,7 +63,6 @@ struct tomoyo_path_info {  	u16 const_len;     /* = tomoyo_const_part_length(name)     */  	bool is_dir;       /* = tomoyo_strendswith(name, "/")      */  	bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ -	u16 depth;         /* = tomoyo_path_depth(name)            */  };  /* diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 5f2e3326337..917f564cdab 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -13,6 +13,8 @@  #include <linux/mount.h>  #include <linux/mnt_namespace.h>  #include <linux/fs_struct.h> +#include <linux/hash.h> +  #include "common.h"  #include "realpath.h" @@ -263,7 +265,8 @@ static unsigned int tomoyo_quota_for_savename;   * table. Frequency of appending strings is very low. So we don't need   * large (e.g. 64k) hash size. 256 will be sufficient.   */ -#define TOMOYO_MAX_HASH 256 +#define TOMOYO_HASH_BITS  8 +#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)  /*   * tomoyo_name_entry is a structure which is used for linking @@ -315,6 +318,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)  	struct tomoyo_free_memory_block_list *fmb;  	int len;  	char *cp; +	struct list_head *head;  	if (!name)  		return NULL; @@ -325,9 +329,10 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)  		return NULL;  	}  	hash = full_name_hash((const unsigned char *) name, len - 1); +	head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; +  	mutex_lock(&lock); -	list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH], -			     list) { +	list_for_each_entry(ptr, head, list) {  		if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))  			goto out;  	} @@ -365,7 +370,7 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)  	tomoyo_fill_path_info(&ptr->entry);  	fmb->ptr += len;  	fmb->len -= len; -	list_add_tail(&ptr->list, &tomoyo_name_list[hash % TOMOYO_MAX_HASH]); +	list_add_tail(&ptr->list, head);  	if (fmb->len == 0) {  		list_del(&fmb->list);  		kfree(fmb); diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 64b859925c0..7717e01fc07 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -131,7 +131,7 @@ static int snd_pdacf_probe(struct pcmcia_device *link)  		return err;  	} -	snd_card_set_dev(card, &handle_to_dev(link)); +	snd_card_set_dev(card, &link->dev);  	pdacf->index = i;  	card_list[i] = card; @@ -142,12 +142,10 @@ static int snd_pdacf_probe(struct pcmcia_device *link)  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;  	link->io.NumPorts1 = 16; -	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT | IRQ_FORCED_PULSE; +	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_FORCED_PULSE;  	// link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; -	link->irq.IRQInfo1 = 0 /* | IRQ_LEVEL_ID */;  	link->irq.Handler = pdacf_interrupt; -	link->irq.Instance = pdacf;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO;  	link->conf.ConfigIndex = 1; diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 1492744ad67..7be3b335704 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -161,11 +161,9 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,  	link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;  	link->io.NumPorts1 = 16; -	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; +	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; -	link->irq.IRQInfo1 = IRQ_LEVEL_ID;  	link->irq.Handler = &snd_vx_irq_handler; -	link->irq.Instance = chip;  	link->conf.Attributes = CONF_ENABLE_IRQ;  	link->conf.IntType = INT_MEMORY_AND_IO; @@ -244,7 +242,7 @@ static int vxpocket_config(struct pcmcia_device *link)  	if (ret)  		goto failed; -	chip->dev = &handle_to_dev(link); +	chip->dev = &link->dev;  	snd_card_set_dev(chip->card, chip->dev);  	if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq.AssignedIRQ) < 0)  |