diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Thu Aug  1 14:17:36 2002
+++ b/CREDITS	Thu Aug  1 14:17:36 2002
@@ -1337,6 +1337,12 @@
 S: Provo, Utah 84606-5607
 S: USA
 
+N: Marcel Holtmann
+E: marcel@holtmann.org
+W: http://www.holtmann.org
+D: Author of the Linux Bluetooth Subsystem PC Card drivers
+S: Germany
+
 N: Rob W. W. Hooft
 E: hooft@EMBL-Heidelberg.DE
 D: Shared libs for graphics-tools and for the f2c compiler
diff -Nru a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
--- a/Documentation/DocBook/Makefile	Thu Aug  1 14:17:40 2002
+++ b/Documentation/DocBook/Makefile	Thu Aug  1 14:17:40 2002
@@ -88,9 +88,9 @@
 IMG-parportbook2 := $(addprefix Documentation/DocBook/,$(IMG-parportbook))
 EPS-parportbook := $(patsubst %.fig,%.eps, $(IMG-parportbook2))
 PNG-parportbook := $(patsubst %.fig,%.png, $(IMG-parportbook2))
-Documentation/DocBook/parportbook.ps: $(EPS-parportbook)
-Documentation/DocBook/parportbook.html Documentation/DocBook/parportbook.pdf:\
-	$(PNG-parportbook)
+Documentation/DocBook/parportbook.html:	$(PNG-parportbook)
+Documentation/DocBook/parportbook.ps Documentation/DocBook/parportbook.pdf:\
+	$(EPS-parportbook)
 
 ###
 # Rules to generate postscript, PDF and HTML
@@ -99,48 +99,44 @@
 	@(which db2ps > /dev/null 2>&1) || \
 	 (echo "*** You need to install DocBook stylesheets ***"; \
 	  exit 1)
-	@echo '  DB2PS   $@'
-	@db2ps -o $(dir $@) $<
+	$(call do_cmd,DB2PS   $@,db2ps -o $(dir $@) $<)
 
 %.pdf : %.sgml
 	@(which db2pdf > /dev/null 2>&1) || \
 	 (echo "*** You need to install DocBook stylesheets ***"; \
 	  exit 1)
-	@echo '  DB2PDF  $@'
-	@db2pdf -o $(dir $@) $<
+	$(call do_cmd,DB2PDF  $@,db2pdf -o $(dir $@) $<)
 
 %.html:	%.sgml
 	@(which db2html > /dev/null 2>&1) || \
 	 (echo "*** You need to install DocBook stylesheets ***"; \
 	  exit 1)
 	@rm -rf $@ $(patsubst %.html,%,$@)
-	@echo '  DB2HTML $@'
-	@db2html -o $(patsubst %.html,%,$@) $< && \
+	$(call do_cmd,DB2HTML $@,db2html -o $(patsubst %.html,%,$@) $< && \
          echo '<a HREF="$(patsubst %.html,%,$(notdir $@))/book1.html">\
-         Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@
+         Goto $(patsubst %.html,%,$(notdir $@))</a><p>' > $@)
 	@if [ ! -z "$(PNG-$(basename $(notdir $@)))" ]; then \
             cp $(PNG-$(basename $(notdir $@))) $(patsubst %.html,%,$@); fi
 
 ###
 # Rules to generate postscripts and PNG imgages from .fig format files
 %.eps: %.fig
-	@echo '  FIG2DEV -Leps $@'
-	@fig2dev -Leps $< $@
+	$(call do_cmd,FIG2DEV -Leps $@,fig2dev -Leps $< $@)
 
 %.png: %.fig
-	@echo '  FIG2DEV -Lpng $@'
-	fig2dev -Lpng $< $@
+	$(call do_cmd,FIG2DEV -Lpng $@,fig2dev -Lpng $< $@)
 
 ###
 # Rule to convert a .c file to inline SGML documentation
 %.sgml: %.c
 	@echo '  Generating $@'
-	@echo "<programlisting>" > $@
-	@expand --tabs=8 < $< | \
-	sed -e "s/&/\\&amp;/g" \
-	     -e "s/</\\&lt;/g" \
-	     -e "s/>/\\&gt;/g" >> $@
-	@echo "</programlisting>" >> $@
+	@(                            \
+	   echo "<programlisting>";   \
+	   expand --tabs=8 < $< |     \
+	   sed -e "s/&/\\&amp;/g"     \
+	       -e "s/</\\&lt;/g"      \
+	       -e "s/>/\\&gt;/g";     \
+	   echo "</programlisting>")  > $@
 
 ###
 # Help targets as used by the top-level makefile
diff -Nru a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog
--- a/Documentation/filesystems/devfs/ChangeLog	Thu Aug  1 14:17:36 2002
+++ b/Documentation/filesystems/devfs/ChangeLog	Thu Aug  1 14:17:36 2002
@@ -1941,3 +1941,19 @@
 - Updated README from master HTML file
 
 - Fixed devfs entry leak in <devfs_readdir> when *readdir fails
+===============================================================================
+Changes for patch v215
+
+- Created <devfs_find_and_unregister>
+
+- Switched many functions from <devfs_find_handle> to
+  <devfs_find_and_unregister>
+
+- Switched many functions from <devfs_find_handle> to <devfs_get_handle>
+===============================================================================
+Changes for patch v216
+
+- Switched arch/ia64/sn/io/hcl.c from <devfs_find_handle> to
+  <devfs_get_handle>
+
+- Removed deprecated <devfs_find_handle>
diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt
--- a/Documentation/ide.txt	Thu Aug  1 14:17:36 2002
+++ b/Documentation/ide.txt	Thu Aug  1 14:17:36 2002
@@ -1,9 +1,6 @@
 
-
-
 	Information regarding the Enhanced IDE drive in Linux 2.5
 
-
 ==============================================================================
 
    
@@ -49,7 +46,7 @@
 - If you mix devices on the same cable, please consider using similar devices
   in respect of the data transfer mode they support.
 
-- Even better tru to stick to the same vendor and device type on the same
+- Even better try to stick to the same vendor and device type on the same
   cable.
 
 ================================================================================
@@ -69,7 +66,8 @@
 To access devices on interfaces > ide0, device entries please make sure that
 device files for them are present in /dev.  If not, please create such
 entries, by simply running the included shell script:
-/usr/src/linux/scripts/MAKEDEV.ide
+
+	/usr/src/linux/scripts/MAKEDEV.ide
 
 This driver automatically probes for most IDE interfaces (including all PCI
 ones), for the drives/geometries attached to those interfaces, and for the IRQ
@@ -195,11 +193,10 @@
 under control of ide.c.   To have ide.c also "take over" the primary
 IDE port in this situation, use the "command line" parameter:  ide0=0x1f0
 
-The IDE driver is partly modularized.  The high level disk/cdrom/tape/floppy
+The IDE driver is modularized.  The high level disk/CD-ROM/tape/floppy
 drivers can always be compiled as loadable modules, the chipset drivers
 can only be compiled into the kernel, and the core code (ide.c) can be
-compiled as a loadable module provided no chipset support and no special
-partition table translations are needed.
+compiled as a loadable module provided no chipset support is needed.
 
 When using ide.c/ide-tape.c as modules in combination with kerneld, add:
 
@@ -217,8 +214,9 @@
 
 ================================================================================
 
-Summary of ide driver parameters for kernel "command line":
-----------------------------------------------------------
+Summary of ide driver parameters for kernel command line
+--------------------------------------------------------
+
  "hdx="  is recognized for all "x" from "a" to "h", such as "hdc".
  
  "idex=" is recognized for all "x" from "0" to "3", such as "ide1".
@@ -300,6 +298,53 @@
 There may be more options than shown -- use the source, Luke!
 
 Everything else is rejected with a "BAD OPTION" message.
+
+================================================================================
+
+IDE ATAPI streaming tape driver
+-------------------------------
+
+This driver is a part of the Linux ide driver and works in co-operation
+with linux/drivers/block/ide.c.
+
+The driver, in co-operation with ide.c, basically traverses the
+request-list for the block device interface. The character device
+interface, on the other hand, creates new requests, adds them
+to the request-list of the block device, and waits for their completion.
+
+Pipelined operation mode is now supported on both reads and writes.
+
+The block device major and minor numbers are determined from the
+tape's relative position in the ide interfaces, as explained in ide.c.
+
+The character device interface consists of the following devices:
+
+ ht0		major 37, minor 0	first  IDE tape, rewind on close.
+ ht1		major 37, minor 1	second IDE tape, rewind on close.
+ ...
+ nht0		major 37, minor 128	first  IDE tape, no rewind on close.
+ nht1		major 37, minor 129	second IDE tape, no rewind on close.
+ ...
+
+Run linux/scripts/MAKEDEV.ide to create the above entries.
+
+The general magnetic tape commands compatible interface, as defined by
+include/linux/mtio.h, is accessible through the character device.
+
+General ide driver configuration options, such as the interrupt-unmask
+flag, can be configured by issuing an ioctl to the block device interface,
+as any other ide device.
+
+Our own ide-tape ioctl's can be issued to either the block device or
+the character device interface.
+
+Maximal throughput with minimal bus load will usually be achieved in the
+following scenario:
+
+	1.	ide-tape is operating in the pipelined operation mode.
+	2.	No buffering is performed by the user backup program.
+
+
 
 ================================================================================
 
diff -Nru a/Documentation/serial/driver b/Documentation/serial/driver
--- a/Documentation/serial/driver	Thu Aug  1 14:17:36 2002
+++ b/Documentation/serial/driver	Thu Aug  1 14:17:36 2002
@@ -138,15 +138,16 @@
 	Stop receiving characters; the port is in the process of
 	being closed.
 
-	Locking: none.
-	Interrupts: caller dependent.
+	Locking: port->lock taken.
+	Interrupts: locally disabled.
 	This call must not sleep
 
   enable_ms(port)
 	Enable the modem status interrupts.
 
-	Locking: none.
-	Interrupts: caller dependent.
+	Locking: port->lock taken.
+	Interrupts: locally disabled.
+	This call must not sleep
 
   break_ctl(port,ctl)
 	Control the transmission of a break signal.  If ctl is
diff -Nru a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
--- a/Documentation/sysctl/vm.txt	Thu Aug  1 14:17:41 2002
+++ b/Documentation/sysctl/vm.txt	Thu Aug  1 14:17:41 2002
@@ -16,7 +16,6 @@
 files can be found in mm/swap.c.
 
 Currently, these files are in /proc/sys/vm:
-- kswapd
 - overcommit_memory
 - page-cluster
 - dirty_async_ratio
@@ -34,39 +33,6 @@
 
 ==============================================================
 
-kswapd:
-
-Kswapd is the kernel swapout daemon. That is, kswapd is that
-piece of the kernel that frees memory when it gets fragmented
-or full. Since every system is different, you'll probably want
-some control over this piece of the system.
-
-The numbers in this page correspond to the numbers in the
-struct pager_daemon {tries_base, tries_min, swap_cluster
-}; The tries_base and swap_cluster probably have the
-largest influence on system performance.
-
-tries_base	The maximum number of pages kswapd tries to
-		free in one round is calculated from this
-		number. Usually this number will be divided
-		by 4 or 8 (see mm/vmscan.c), so it isn't as
-		big as it looks.
-		When you need to increase the bandwidth to/from
-		swap, you'll want to increase this number.
-tries_min	This is the minimum number of times kswapd
-		tries to free a page each time it is called.
-		Basically it's just there to make sure that
-		kswapd frees some pages even when it's being
-		called with minimum priority.
-swap_cluster	This is the number of pages kswapd writes in
-		one turn. You want this large so that kswapd
-		does it's I/O in large chunks and the disk
-		doesn't have to seek often, but you don't want
-		it to be too large since that would flood the
-		request queue.
-
-==============================================================
-
 overcommit_memory:
 
 This value contains a flag that enables memory overcommitment.
@@ -78,7 +44,21 @@
 programs that malloc() huge amounts of memory "just-in-case"
 and don't use much of it.
 
-Look at: mm/mmap.c::vm_enough_memory() for more information.
+A value  of 2 introduces a new "strict overcommit" policy
+that attempts to prevent any overcommit of memory.
+
+The default value is 0.
+
+See Documentation/vm/overcommit-accounting and
+mm/mmap.c::vm_enough_memory() for more information.
+
+==============================================================
+
+overcommit_ratio:
+
+When overcommit_memory is set to 2, the committed address
+space is not permitted to exceed swap plus this percentage
+of physical RAM.  See above.
 
 ==============================================================
 
diff -Nru a/Documentation/vm/overcommit-accounting b/Documentation/vm/overcommit-accounting
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/vm/overcommit-accounting	Thu Aug  1 14:17:41 2002
@@ -0,0 +1,68 @@
+The Linux kernel supports four overcommit handling modes
+
+0	-	Heuristic overcommit handling. Obvious overcommits of
+		address space are refused. Used for a typical system. It
+		ensures a seriously wild allocation fails while allowing
+		overcommit to reduce swap usage.  This is the default.
+
+1	-	No overcommit handling. Appropriate for some scientific
+		applications.
+
+2	-	(NEW) strict overcommit. The total address space commit
+		for the system is not permitted to exceed swap + a
+		configurable percentage (default is 50) of physical RAM.
+		Depending on the percentage you use, in most situations
+		this means a process will not be killed while accessing
+		pages but will receive errors on memory allocation as
+		appropriate.
+
+The overcommit policy is set via the sysctl `vm.overcommit_memory'.
+
+The overcommit percentage is set via `vm.overcommit_ratio'.
+
+Gotchas
+-------
+
+The C language stack growth does an implicit mremap. If you want absolute
+guarantees and run close to the edge you MUST mmap your stack for the 
+largest size you think you will need. For typical stack usage is does
+not matter much but its a corner case if you really really care
+
+In mode 2 the MAP_NORESERVE flag is ignored. 
+
+
+How It Works
+------------
+
+The overcommit is based on the following rules
+
+For a file backed map
+	SHARED or READ-only	-	0 cost (the file is the map not swap)
+	PRIVATE WRITABLE	-	size of mapping per instance
+
+For an anonymous or /dev/zero map
+	SHARED			-	size of mapping
+	PRIVATE READ-only	-	0 cost (but of little use)
+	PRIVATE WRITABLE	-	size of mapping per instance
+
+Additional accounting
+	Pages made writable copies by mmap
+	shmfs memory drawn from the same pool
+
+Status
+------
+
+o	We account mmap memory mappings
+o	We account mprotect changes in commit
+o	We account mremap changes in size
+o	We account brk
+o	We account munmap
+o	We report the commit status in /proc
+o	Account and check on fork
+o	Review stack handling/building on exec
+o	SHMfs accounting
+o	Implement actual limit enforcement
+
+To Do
+-----
+o	Account ptrace pages (this is hard)
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Thu Aug  1 14:17:40 2002
+++ b/MAINTAINERS	Thu Aug  1 14:17:40 2002
@@ -270,6 +270,12 @@
 W:	http://bluez.sf.net
 S:	Maintained
 
+BLUETOOTH SUBSYSTEM (PC Card Drivers)
+P:	Marcel Holtmann
+M:	marcel@holtmann.org
+W:	http://www.holtmann.org/linux/bluetooth/
+S:	Maintained
+
 BTTV VIDEO4LINUX DRIVER
 P:	Gerd Knorr
 M:	kraxel@bytesex.org
@@ -1487,7 +1493,7 @@
 L:	alsa-devel@alsa-project.org
 S:	Maintained
 
-SPARC:
+UltraSPARC (sparc64):
 P:	David S. Miller
 M:	davem@redhat.com
 P:	Eddie C. Dost
@@ -1499,6 +1505,9 @@
 L:	sparclinux@vger.kernel.org
 L:	ultralinux@vger.kernel.org
 S:	Maintained
+
+SPARC (sparc32):
+S:	Unmaintained
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
 P:	Roger Wolff
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Thu Aug  1 14:17:36 2002
+++ b/Makefile	Thu Aug  1 14:17:36 2002
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 5
-SUBLEVEL = 29
+SUBLEVEL = 30
 EXTRAVERSION =
 
 # *DOCUMENTATION*
@@ -279,7 +279,6 @@
 	mv -f .tmpversion .version
 	+$(MAKE) -C init
 	$(call cmd,link_vmlinux)
-	$(cmd_link_vmlinux)
 	echo 'cmd_$@ := $(cmd_link_vmlinux)' > $(@D)/.$(@F).cmd
 	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
 endef
diff -Nru a/Rules.make b/Rules.make
--- a/Rules.make	Thu Aug  1 14:17:40 2002
+++ b/Rules.make	Thu Aug  1 14:17:40 2002
@@ -553,3 +553,22 @@
 # If quiet is set, only print short version of command
 
 cmd = @$(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
+
+# do_cmd is a shorthand used to support both compressed, verbose
+# and silent output in a single line.
+# Compared to cmd described avobe, do_cmd does no rely on any variables 
+# previously assigned a value.
+#
+# Usage $(call do_cmd,CMD   $@,cmd_to_execute bla bla)
+# Example:
+# $(call do_cmd,CP $@,cp -b $< $@)
+# make -s => nothing will be printed
+# make KBUILD_VERBOSE=1 => cp -b path/to/src.file path/to/dest.file
+# make KBUILD_VERBOSE=0 =>   CP path/to/dest.file
+define do_cmd
+        @$(if $(filter quiet_,$(quiet)), echo '  $(1)' &&,
+           $(if $(filter silent_,$(quiet)),,
+             echo "$(2)" &&)) \
+        $(2)
+endef
+
diff -Nru a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
--- a/arch/alpha/kernel/entry.S	Thu Aug  1 14:17:36 2002
+++ b/arch/alpha/kernel/entry.S	Thu Aug  1 14:17:36 2002
@@ -1081,8 +1081,8 @@
 	.quad sys_pciconfig_write
 	.quad sys_query_module
 	.quad sys_prctl
-	.quad sys_pread
-	.quad sys_pwrite			/* 350 */
+	.quad sys_pread64
+	.quad sys_pwrite64			/* 350 */
 	.quad sys_rt_sigreturn
 	.quad sys_rt_sigaction
 	.quad sys_rt_sigprocmask
diff -Nru a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
--- a/arch/alpha/kernel/osf_sys.c	Thu Aug  1 14:17:36 2002
+++ b/arch/alpha/kernel/osf_sys.c	Thu Aug  1 14:17:36 2002
@@ -221,8 +221,8 @@
 	 * isn't actually going to matter, as if the parent happens
 	 * to change we can happily return either of the pids.
 	 */
-	(&regs)->r20 = tsk->real_parent->pid;
-	return tsk->pid;
+	(&regs)->r20 = tsk->real_parent->tgid;
+	return tsk->tgid;
 }
 
 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/kernel/calls.S	Thu Aug  1 14:17:40 2002
@@ -194,8 +194,8 @@
 		.long	sys_rt_sigtimedwait
 		.long	sys_rt_sigqueueinfo
 		.long	sys_rt_sigsuspend_wrapper
-/* 180 */	.long	sys_pread
-		.long	sys_pwrite
+/* 180 */	.long	sys_pread64
+		.long	sys_pwrite64
 		.long	sys_chown16
 		.long	sys_getcwd
 		.long	sys_capget
@@ -237,7 +237,7 @@
 /* 220 */	.long	sys_madvise
 		.long	sys_fcntl64
 		.long	sys_ni_syscall /* TUX */
-		.long	sys_ni_syscall /* Security */
+		.long	sys_security
 		.long	sys_gettid
 /* 225 */	.long	sys_readahead
 		.long	sys_setxattr
diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
--- a/arch/arm/kernel/entry-armv.S	Thu Aug  1 14:17:39 2002
+++ b/arch/arm/kernel/entry-armv.S	Thu Aug  1 14:17:39 2002
@@ -725,7 +725,7 @@
 		msr	cpsr_c, r9
 		mov	r2, sp
 		bl	do_DataAbort
-		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC
+		disable_irq r0
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -776,9 +776,9 @@
 		movne	pc, lr
 		mov	r7, #PREEMPT_ACTIVE
 		str	r7, [r8, #TI_PREEMPT]		@ set PREEMPT_ACTIVE
-1:		set_cpsr_c r2, #MODE_SVC		@ enable IRQs
+1:		enable_irq r2				@ enable IRQs
 		bl	schedule
-		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC	@ disable IRQs
+		disable_irq r0				@ disable IRQs
 		ldr	r0, [r8, #TI_FLAGS]		@ get new tasks TI_FLAGS
 		tst	r0, #_TIF_NEED_RESCHED
 		beq	preempt_return			@ go again
@@ -801,7 +801,7 @@
 		mov	r0, sp				@ struct pt_regs *regs
 		bl	do_undefinstr
 
-1:		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC
+1:		disable_irq r0
 		ldr	lr, [sp, #S_PSR]		@ Get SVC cpsr
 		msr	spsr, lr
 		ldmia	sp, {r0 - pc}^			@ Restore SVC registers
@@ -822,7 +822,7 @@
 		mov	r0, r2				@ address (pc)
 		mov	r1, sp				@ regs
 		bl	do_PrefetchAbort		@ call abort handler
-		set_cpsr_c r0, #PSR_I_BIT | MODE_SVC
+		disable_irq r0
 		ldr	r0, [sp, #S_PSR]
 		msr	spsr, r0
 		ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
@@ -861,7 +861,7 @@
 #else
 		bl	CPU_ABORT_HANDLER
 #endif
-		set_cpsr_c r2, #MODE_SVC		@ Enable interrupts
+		enable_irq r2				@ Enable interrupts
 		mov	r2, sp
 		adrsvc	al, lr, ret_from_exception
 		b	do_DataAbort
@@ -916,7 +916,7 @@
 		adrsvc	al, r9, ret_from_exception	@ r9  = normal FP return
 		adrsvc	al, lr, fpundefinstr		@ lr  = undefined instr return
 
-call_fpe:	set_cpsr_c r0, #MODE_SVC		@ Enable interrupts
+call_fpe:	enable_irq r0				@ Enable interrupts
 		get_thread_info r10			@ get current thread
 		ldr	r4, [r10, #TI_TASK]		@ get current task
 		mov	r8, #1
@@ -939,7 +939,7 @@
 		stmdb	r8, {sp, lr}^			@ Save sp_usr lr_usr
 		alignment_trap r4, r7, __temp_abt
 		zero_fp
-		set_cpsr_c r0, #MODE_SVC		@ Enable interrupts
+		enable_irq r0				@ Enable interrupts
 		mov	r0, r5				@ address (pc)
 		mov	r1, sp				@ regs
 		bl	do_PrefetchAbort		@ call abort handler
diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
--- a/arch/arm/kernel/entry-common.S	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/kernel/entry-common.S	Thu Aug  1 14:17:36 2002
@@ -35,18 +35,27 @@
  * stack.
  */
 ret_fast_syscall:
-	set_cpsr_c r1, #PSR_I_BIT | MODE_SVC	@ disable interrupts
+	disable_irq r1				@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
-	bne	ret_fast_work
+	bne	fast_work_pending
 	fast_restore_user_regs
 
 /*
  * Ok, we need to do extra processing, enter the slow path.
  */
-ret_fast_work:
-	str	r0, [sp, #S_R0+S_OFF]!	@ returned r0
-	b	work_pending
+fast_work_pending:
+	str	r0, [sp, #S_R0+S_OFF]!		@ returned r0
+work_pending:
+	tst	r1, #_TIF_NEED_RESCHED
+	bne	work_resched
+	tst	r1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING
+	beq	no_work_pending
+	mov	r0, sp				@ 'regs'
+	mov	r2, why				@ 'syscall'
+	bl	do_notify_resume
+	disable_irq r1				@ disable interrupts
+	b	no_work_pending
 
 work_resched:
 	bl	schedule
@@ -55,22 +64,12 @@
  */
 ENTRY(ret_to_user)
 ret_slow_syscall:
-	set_cpsr_c r1, #PSR_I_BIT | MODE_SVC	@ disable interrupts
+	disable_irq r1				@ disable interrupts
 	ldr	r1, [tsk, #TI_FLAGS]
 	tst	r1, #_TIF_WORK_MASK
-	beq	no_work_pending
-work_pending:
-	tst	r1, #_TIF_NEED_RESCHED
-	bne	work_resched
-	tst	r1, #_TIF_NOTIFY_RESUME | _TIF_SIGPENDING
-	blne	__do_notify_resume
+	bne	work_pending
 no_work_pending:
-	restore_user_regs
-
-__do_notify_resume:
-	mov	r0, sp				@ 'regs'
-	mov	r2, why				@ 'syscall'
-	b	do_notify_resume		@ note the bl above sets lr
+	slow_restore_user_regs
 
 /*
  * This is how we return from a fork.
@@ -80,9 +79,9 @@
 	bl	schedule_tail
 #endif
 	get_thread_info tsk
-	ldr	ip, [tsk, #TI_FLAGS]		@ check for syscall tracing
+	ldr	r1, [tsk, #TI_FLAGS]		@ check for syscall tracing
 	mov	why, #1
-	tst	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+	tst	r1, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
 	beq	ret_slow_syscall
 	mov	r1, sp
 	mov	r0, #1				@ trace exit [IP = 1]
@@ -134,7 +133,7 @@
 	ldr	ip, [ip]
 	mcr	p15, 0, ip, c1, c0		@ update control register
 #endif
-	enable_irqs ip
+	enable_irq ip
 
 	str	r4, [sp, #-S_OFF]!		@ push fifth arg
 
diff -Nru a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
--- a/arch/arm/kernel/entry-header.S	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/kernel/entry-header.S	Thu Aug  1 14:17:40 2002
@@ -11,13 +11,13 @@
 #define MODE_SVC 0x13
 #endif
 
-		.macro	zero_fp
+	.macro	zero_fp
 #ifndef CONFIG_NO_FRAME_POINTER
-		mov	fp, #0
+	mov	fp, #0
 #endif
-		.endm
+	.endm
 
-		.text
+	.text
 
 @ Bad Abort numbers
 @ -----------------
@@ -69,119 +69,146 @@
 #define S_OFF		8
 
 #ifdef CONFIG_CPU_32
-		.macro	save_user_regs
-		sub	sp, sp, #S_FRAME_SIZE
-		stmia	sp, {r0 - r12}			@ Calling r0 - r12
-		add	r8, sp, #S_PC
-		stmdb	r8, {sp, lr}^			@ Calling sp, lr
-		mrs	r8, spsr			@ called from non-FIQ mode, so ok.
-		str	lr, [sp, #S_PC]			@ Save calling PC
-		str	r8, [sp, #S_PSR]		@ Save CPSR
-		str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
-		.endm
-
-		.macro	restore_user_regs
-		ldr	r0, [sp, #S_PSR]		@ Get calling cpsr
-		mov	ip, #PSR_I_BIT | MODE_SVC
-		msr	cpsr_c, ip			@ disable IRQs
-		msr	spsr, r0			@ save in spsr_svc
-		ldr	lr, [sp, #S_PC]			@ Get PC
-		ldmia	sp, {r0 - lr}^			@ Get calling r0 - lr
-		mov	r0, r0
-		add	sp, sp, #S_FRAME_SIZE
-		movs	pc, lr				@ return & move spsr_svc into cpsr
-		.endm
-
-		.macro	fast_restore_user_regs
-		mov	ip, #PSR_I_BIT | MODE_SVC
-		msr	cpsr_c, ip			@ disable IRQs
-		ldr	r1, [sp, #S_OFF + S_PSR]	@ get calling cpsr
-		ldr	lr, [sp, #S_OFF + S_PC]!	@ get pc
- 		msr	spsr, r1			@ save in spsr_svc
-		ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
-		mov	r0, r0
-		add	sp, sp, #S_FRAME_SIZE - S_PC
-		movs	pc, lr				@ return & move spsr_svc into cpsr
-		.endm
-
-		.macro	mask_pc, rd, rm
-		.endm
-
-		.macro	enable_irqs, temp
-		mov	\temp, #MODE_SVC
-		msr	cpsr_c, \temp
-		.endm
-
-		.macro	get_thread_info, rd
-		mov	\rd, sp, lsr #13
-		mov	\rd, \rd, lsl #13
-		.endm
-
-		/*
-		 * Like adr, but force SVC mode (if required)
-		 */
-		.macro	adrsvc, cond, reg, label
-		adr\cond	\reg, \label
-		.endm
 
-		.macro	alignment_trap, rbase, rtemp, sym
+	.macro	set_cpsr_c, reg, mode
+#if 1
+	/* broken binutils */
+	mov	\reg, \mode
+	msr	cpsr_c, \reg
+#else
+	msr	cpsr_c, \mode
+#endif
+	.endm
+
+	.macro	disable_irq, temp
+	set_cpsr_c \temp, #PSR_I_BIT | MODE_SVC
+	.endm
+
+	.macro	enable_irq, temp
+	set_cpsr_c \temp, #MODE_SVC
+	.endm
+
+	.macro	save_user_regs
+	sub	sp, sp, #S_FRAME_SIZE
+	stmia	sp, {r0 - r12}			@ Calling r0 - r12
+	add	r8, sp, #S_PC
+	stmdb	r8, {sp, lr}^			@ Calling sp, lr
+	mrs	r8, spsr			@ called from non-FIQ mode, so ok.
+	str	lr, [sp, #S_PC]			@ Save calling PC
+	str	r8, [sp, #S_PSR]		@ Save CPSR
+	str	r0, [sp, #S_OLD_R0]		@ Save OLD_R0
+	.endm
+
+	.macro	restore_user_regs
+	ldr	r1, [sp, #S_PSR]		@ Get calling cpsr
+	disable_irq ip				@ disable IRQs
+	ldr	lr, [sp, #S_PC]!		@ Get PC
+	msr	spsr, r1			@ save in spsr_svc
+	ldmdb	sp, {r0 - lr}^			@ Get calling r0 - lr
+	mov	r0, r0
+	add	sp, sp, #S_FRAME_SIZE - S_PC
+	movs	pc, lr				@ return & move spsr_svc into cpsr
+	.endm
+
+/*
+ * Must be called with IRQs already disabled.
+ */
+	.macro	fast_restore_user_regs
+	ldr	r1, [sp, #S_OFF + S_PSR]	@ get calling cpsr
+	ldr	lr, [sp, #S_OFF + S_PC]!	@ get pc
+	msr	spsr, r1			@ save in spsr_svc
+	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
+	mov	r0, r0
+	add	sp, sp, #S_FRAME_SIZE - S_PC
+	movs	pc, lr				@ return & move spsr_svc into cpsr
+	.endm
+
+/*
+ * Must be called with IRQs already disabled.
+ */
+	.macro	slow_restore_user_regs
+	ldr	r1, [sp, #S_PSR]		@ get calling cpsr
+	ldr	lr, [sp, #S_PC]!		@ get pc
+	msr	spsr, r1			@ save in spsr_svc
+	ldmdb	sp, {r0 - lr}^			@ get calling r1 - lr
+	mov	r0, r0
+	add	sp, sp, #S_FRAME_SIZE - S_PC
+	movs	pc, lr				@ return & move spsr_svc into cpsr
+	.endm
+
+	.macro	mask_pc, rd, rm
+	.endm
+
+	.macro	get_thread_info, rd
+	mov	\rd, sp, lsr #13
+	mov	\rd, \rd, lsl #13
+	.endm
+
+/*
+ * Like adr, but force SVC mode (if required)
+ */
+	.macro	adrsvc, cond, reg, label
+	adr\cond	\reg, \label
+	.endm
+
+	.macro	alignment_trap, rbase, rtemp, sym
 #ifdef CONFIG_ALIGNMENT_TRAP
 #define OFF_CR_ALIGNMENT(x)	cr_alignment - x
 
-		ldr	\rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
-		mcr	p15, 0, \rtemp, c1, c0
+	ldr	\rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
+	mcr	p15, 0, \rtemp, c1, c0
 #endif
-		.endm
+	.endm
 
 #else
-		.macro	save_user_regs
-		str	r0, [sp, #-4]!
-		str	lr, [sp, #-4]!
-		sub	sp, sp, #15*4
-		stmia	sp, {r0 - lr}^
-		mov	r0, r0
-		.endm
-
-		.macro	restore_user_regs
-		ldmia	sp, {r0 - lr}^
-		mov	r0, r0
-		ldr	lr, [sp, #15*4]
-		add	sp, sp, #15*4+8
-		movs	pc, lr
-		.endm
-
-		.macro	fast_restore_user_regs
-		add	sp, sp, #S_OFF
-		ldmib	sp, {r1 - lr}^
-		mov	r0, r0
-		ldr	lr, [sp, #15*4]
-		add	sp, sp, #15*4+8
-		movs	pc, lr
-		.endm
-
-		.macro	mask_pc, rd, rm
-		bic	\rd, \rm, #PCMASK
-		.endm
-
-		.macro	enable_irqs, temp
-		teqp	pc, #0x00000003
-		.endm
-
-		.macro	initialise_traps_extra
-		.endm
-
-		.macro	get_thread_info, rd
-		mov	\rd, sp, lsr #13
-		mov	\rd, \rd, lsl #13
-		.endm
-
-		/*
-		 * Like adr, but force SVC mode (if required)
-		 */
-		.macro	adrsvc, cond, reg, label
-		adr\cond	\reg, \label
-		orr\cond	\reg, \reg, #0x08000003
-		.endm
+	.macro	save_user_regs
+	str	r0, [sp, #-4]!
+	str	lr, [sp, #-4]!
+	sub	sp, sp, #15*4
+	stmia	sp, {r0 - lr}^
+	mov	r0, r0
+	.endm
+
+	.macro	restore_user_regs
+	ldmia	sp, {r0 - lr}^
+	mov	r0, r0
+	ldr	lr, [sp, #15*4]
+	add	sp, sp, #15*4+8
+	movs	pc, lr
+	.endm
+
+	.macro	fast_restore_user_regs
+	add	sp, sp, #S_OFF
+	ldmib	sp, {r1 - lr}^
+	mov	r0, r0
+	ldr	lr, [sp, #15*4]
+	add	sp, sp, #15*4+8
+	movs	pc, lr
+	.endm
+
+	.macro	mask_pc, rd, rm
+	bic	\rd, \rm, #PCMASK
+	.endm
+
+	.macro	enable_irqs, temp
+	teqp	pc, #0x00000003
+	.endm
+
+	.macro	initialise_traps_extra
+	.endm
+
+	.macro	get_thread_info, rd
+	mov	\rd, sp, lsr #13
+	mov	\rd, \rd, lsl #13
+	.endm
+
+	/*
+	 * Like adr, but force SVC mode (if required)
+	 */
+	.macro	adrsvc, cond, reg, label
+	adr\cond	\reg, \label
+	orr\cond	\reg, \reg, #0x08000003
+	.endm
 
 #endif
 
@@ -215,13 +242,3 @@
 	ldr	scno, [lr, #-4]		@ get SWI instruction
 #endif
 	.endm
-
-	.macro	set_cpsr_c, reg, mode
-#if 1
-	mov	\reg, \mode
-	msr	cpsr_c, \reg
-#else
-	msr	cpsr_c, \mode
-#endif
-	.endm
-
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/kernel/irq.c	Thu Aug  1 14:17:36 2002
@@ -217,14 +217,14 @@
 
 	desc->triggered = 1;
 
-	irq_enter(cpu, irq);
+	irq_enter();
 	kstat.irqs[cpu][irq]++;
 
 	action = desc->action;
 	if (action)
 		__do_irq(irq, desc->action, regs);
 
-	irq_exit(cpu, irq);
+	irq_exit();
 }
 
 /*
@@ -256,7 +256,7 @@
 	 */
 	desc->running = 1;
 
-	irq_enter(cpu, irq);
+	irq_enter();
 	kstat.irqs[cpu][irq]++;
 
 	do {
@@ -274,7 +274,7 @@
 		__do_irq(irq, action, regs);
 	} while (desc->pending);
 
-	irq_exit(cpu, irq);
+	irq_exit();
 
 	desc->running = 0;
 
@@ -311,7 +311,7 @@
 	desc->chip->ack(irq);
 
 	if (likely(desc->enabled)) {
-		irq_enter(cpu, irq);
+		irq_enter();
 		kstat.irqs[cpu][irq]++;
 
 		/*
@@ -325,7 +325,7 @@
 				   !check_irq_lock(desc, irq, regs)))
 				desc->chip->unmask(irq);
 		}
-		irq_exit(cpu, irq);
+		irq_exit();
 	}
 }
 
diff -Nru a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
--- a/arch/arm/kernel/ptrace.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/kernel/ptrace.c	Thu Aug  1 14:17:36 2002
@@ -17,6 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/security.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -654,6 +655,9 @@
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
 		if (current->ptrace & PT_PTRACED)
+			goto out;
+		ret = security_ops->ptrace(current->parent, current);
+		if (ret)
 			goto out;
 		/* set the ptrace bit in the process flags. */
 		current->ptrace |= PT_PTRACED;
diff -Nru a/arch/arm/lib/kbd.c b/arch/arm/lib/kbd.c
--- a/arch/arm/lib/kbd.c	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/lib/kbd.c	Thu Aug  1 14:17:40 2002
@@ -1,13 +1,279 @@
 #include <linux/config.h>
 #include <linux/kd.h>
+#include <linux/kbd_ll.h>
+#include <linux/kbd_kern.h>
 
-int  (*k_setkeycode)(unsigned int, unsigned int);
-int  (*k_getkeycode)(unsigned int);
-int  (*k_translate)(unsigned char, unsigned char *, char);
-char (*k_unexpected_up)(unsigned char);
+/*
+ * Translation of escaped scancodes to keycodes.
+ * This is now user-settable.
+ * The keycodes 1-88,96-111,119 are fairly standard, and
+ * should probably not be changed - changing might confuse X.
+ * X also interprets scancode 0x5d (KEY_Begin).
+ *
+ * For 1-88 keycode equals scancode.
+ */
+
+#define E0_KPENTER 96
+#define E0_RCTRL   97
+#define E0_KPSLASH 98
+#define E0_PRSCR   99
+#define E0_RALT    100
+#define E0_BREAK   101		/* (control-pause) */
+#define E0_HOME    102
+#define E0_UP      103
+#define E0_PGUP    104
+#define E0_LEFT    105
+#define E0_RIGHT   106
+#define E0_END     107
+#define E0_DOWN    108
+#define E0_PGDN    109
+#define E0_INS     110
+#define E0_DEL     111
+
+/* for USB 106 keyboard */
+#define E0_YEN         124
+#define E0_BACKSLASH   89
+
+
+#define E1_PAUSE   119
+
+/*
+ * The keycodes below are randomly located in 89-95,112-118,120-127.
+ * They could be thrown away (and all occurrences below replaced by 0),
+ * but that would force many users to use the `setkeycodes' utility, where
+ * they needed not before. It does not matter that there are duplicates, as
+ * long as no duplication occurs for any single keyboard.
+ */
+#define SC_LIM 89
+
+#define FOCUS_PF1 85		/* actual code! */
+#define FOCUS_PF2 89
+#define FOCUS_PF3 90
+#define FOCUS_PF4 91
+#define FOCUS_PF5 92
+#define FOCUS_PF6 93
+#define FOCUS_PF7 94
+#define FOCUS_PF8 95
+#define FOCUS_PF9 120
+#define FOCUS_PF10 121
+#define FOCUS_PF11 122
+#define FOCUS_PF12 123
+
+#define JAP_86     124
+/* tfj@olivia.ping.dk:
+ * The four keys are located over the numeric keypad, and are
+ * labelled A1-A4. It's an rc930 keyboard, from
+ * Regnecentralen/RC International, Now ICL.
+ * Scancodes: 59, 5a, 5b, 5c.
+ */
+#define RGN1 124
+#define RGN2 125
+#define RGN3 126
+#define RGN4 127
+
+static unsigned char high_keys[128 - SC_LIM] = {
+	RGN1, RGN2, RGN3, RGN4, 0, 0, 0,	/* 0x59-0x5f */
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x60-0x67 */
+	0, 0, 0, 0, 0, FOCUS_PF11, 0, FOCUS_PF12,	/* 0x68-0x6f */
+	0, 0, 0, FOCUS_PF2, FOCUS_PF9, 0, 0, FOCUS_PF3,	/* 0x70-0x77 */
+	FOCUS_PF4, FOCUS_PF5, FOCUS_PF6, FOCUS_PF7,	/* 0x78-0x7b */
+	FOCUS_PF8, JAP_86, FOCUS_PF10, 0	/* 0x7c-0x7f */
+};
+
+/* BTC */
+#define E0_MACRO   112
+/* LK450 */
+#define E0_F13     113
+#define E0_F14     114
+#define E0_HELP    115
+#define E0_DO      116
+#define E0_F17     117
+#define E0_KPMINPLUS 118
+/*
+ * My OmniKey generates e0 4c for  the "OMNI" key and the
+ * right alt key does nada. [kkoller@nyx10.cs.du.edu]
+ */
+#define E0_OK  124
+/*
+ * New microsoft keyboard is rumoured to have
+ * e0 5b (left window button), e0 5c (right window button),
+ * e0 5d (menu button). [or: LBANNER, RBANNER, RMENU]
+ * [or: Windows_L, Windows_R, TaskMan]
+ */
+#define E0_MSLW        125
+#define E0_MSRW        126
+#define E0_MSTM        127
+
+static unsigned char e0_keys[128] = {
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x00-0x07 */
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x08-0x0f */
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x10-0x17 */
+	0, 0, 0, 0, E0_KPENTER, E0_RCTRL, 0, 0,	/* 0x18-0x1f */
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x20-0x27 */
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x28-0x2f */
+	0, 0, 0, 0, 0, E0_KPSLASH, 0, E0_PRSCR,	/* 0x30-0x37 */
+	E0_RALT, 0, 0, 0, 0, E0_F13, E0_F14, E0_HELP,	/* 0x38-0x3f */
+	E0_DO, E0_F17, 0, 0, 0, 0, E0_BREAK, E0_HOME,	/* 0x40-0x47 */
+	E0_UP, E0_PGUP, 0, E0_LEFT, E0_OK, E0_RIGHT, E0_KPMINPLUS, E0_END,	/* 0x48-0x4f */
+	E0_DOWN, E0_PGDN, E0_INS, E0_DEL, 0, 0, 0, 0,	/* 0x50-0x57 */
+	0, 0, 0, E0_MSLW, E0_MSRW, E0_MSTM, 0, 0,	/* 0x58-0x5f */
+	0, 0, 0, 0, 0, 0, 0, 0,	/* 0x60-0x67 */
+	0, 0, 0, 0, 0, 0, 0, E0_MACRO,	/* 0x68-0x6f */
+	//0, 0, 0, 0, 0, 0, 0, 0,                          /* 0x70-0x77 */
+	0, 0, 0, 0, 0, E0_BACKSLASH, 0, 0,	/* 0x70-0x77 */
+	0, 0, 0, E0_YEN, 0, 0, 0, 0	/* 0x78-0x7f */
+};
+
+static int gen_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	if (scancode < SC_LIM || scancode > 255 || keycode > 127)
+		return -EINVAL;
+	if (scancode < 128)
+		high_keys[scancode - SC_LIM] = keycode;
+	else
+		e0_keys[scancode - 128] = keycode;
+	return 0;
+}
+
+static int gen_getkeycode(unsigned int scancode)
+{
+	return
+	    (scancode < SC_LIM || scancode > 255) ? -EINVAL :
+	    (scancode <
+	     128) ? high_keys[scancode - SC_LIM] : e0_keys[scancode - 128];
+}
+
+static int
+gen_translate(unsigned char scancode, unsigned char *keycode, char raw_mode)
+{
+	static int prev_scancode = 0;
+
+	/* special prefix scancodes.. */
+	if (scancode == 0xe0 || scancode == 0xe1) {
+		prev_scancode = scancode;
+		return 0;
+	}
+
+	/* 0xFF is sent by a few keyboards, ignore it. 0x00 is error */
+	if (scancode == 0x00 || scancode == 0xff) {
+		prev_scancode = 0;
+		return 0;
+	}
+
+	scancode &= 0x7f;
+
+	if (prev_scancode) {
+		/*
+		 * usually it will be 0xe0, but a Pause key generates
+		 * e1 1d 45 e1 9d c5 when pressed, and nothing when released
+		 */
+		if (prev_scancode != 0xe0) {
+			if (prev_scancode == 0xe1 && scancode == 0x1d) {
+				prev_scancode = 0x100;
+				return 0;
+			}
+				else if (prev_scancode == 0x100
+					 && scancode == 0x45) {
+				*keycode = E1_PAUSE;
+				prev_scancode = 0;
+			} else {
+#ifdef KBD_REPORT_UNKN
+				if (!raw_mode)
+					printk(KERN_INFO
+					       "keyboard: unknown e1 escape sequence\n");
+#endif
+				prev_scancode = 0;
+				return 0;
+			}
+		} else {
+			prev_scancode = 0;
+			/*
+			 *  The keyboard maintains its own internal caps lock and
+			 *  num lock statuses. In caps lock mode E0 AA precedes make
+			 *  code and E0 2A follows break code. In num lock mode,
+			 *  E0 2A precedes make code and E0 AA follows break code.
+			 *  We do our own book-keeping, so we will just ignore these.
+			 */
+			/*
+			 *  For my keyboard there is no caps lock mode, but there are
+			 *  both Shift-L and Shift-R modes. The former mode generates
+			 *  E0 2A / E0 AA pairs, the latter E0 B6 / E0 36 pairs.
+			 *  So, we should also ignore the latter. - aeb@cwi.nl
+			 */
+			if (scancode == 0x2a || scancode == 0x36)
+				return 0;
+
+			if (e0_keys[scancode])
+				*keycode = e0_keys[scancode];
+			else {
+#ifdef KBD_REPORT_UNKN
+				if (!raw_mode)
+					printk(KERN_INFO
+					       "keyboard: unknown scancode e0 %02x\n",
+					       scancode);
+#endif
+				return 0;
+			}
+		}
+	} else if (scancode >= SC_LIM) {
+		/* This happens with the FOCUS 9000 keyboard
+		   Its keys PF1..PF12 are reported to generate
+		   55 73 77 78 79 7a 7b 7c 74 7e 6d 6f
+		   Moreover, unless repeated, they do not generate
+		   key-down events, so we have to zero up_flag below */
+		/* Also, Japanese 86/106 keyboards are reported to
+		   generate 0x73 and 0x7d for \ - and \ | respectively. */
+		/* Also, some Brazilian keyboard is reported to produce
+		   0x73 and 0x7e for \ ? and KP-dot, respectively. */
+
+		*keycode = high_keys[scancode - SC_LIM];
+
+		if (!*keycode) {
+			if (!raw_mode) {
+#ifdef KBD_REPORT_UNKN
+				printk(KERN_INFO
+				       "keyboard: unrecognized scancode (%02x)"
+				       " - ignored\n", scancode);
+#endif
+			}
+			return 0;
+		}
+	} else
+		*keycode = scancode;
+	return 1;
+}
+
+static char gen_unexpected_up(unsigned char keycode)
+{
+	/* unexpected, but this can happen: maybe this was a key release for a
+	   FOCUS 9000 PF key; if we want to see it, we have to clear up_flag */
+	if (keycode >= SC_LIM || keycode == 85)
+		return 0;
+	else
+		return 0200;
+}
+
+/*
+ * These are the default mappings
+ */
+int  (*k_setkeycode)(unsigned int, unsigned int) = gen_setkeycode;
+int  (*k_getkeycode)(unsigned int) = gen_getkeycode;
+int  (*k_translate)(unsigned char, unsigned char *, char) = gen_translate;
+char (*k_unexpected_up)(unsigned char) = gen_unexpected_up;
 void (*k_leds)(unsigned char);
 
+/* Simple translation table for the SysRq keys */
+
 #ifdef CONFIG_MAGIC_SYSRQ
-int k_sysrq_key;
-unsigned char *k_sysrq_xlate;
+static unsigned char gen_sysrq_xlate[128] =
+	"\000\0331234567890-=\177\t"	/* 0x00 - 0x0f */
+	"qwertyuiop[]\r\000as"	/* 0x10 - 0x1f */
+	"dfghjkl;'`\000\\zxcv"	/* 0x20 - 0x2f */
+	"bnm,./\000*\000 \000\201\202\203\204\205"	/* 0x30 - 0x3f */
+	"\206\207\210\211\212\000\000789-456+1"	/* 0x40 - 0x4f */
+	"230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000"	/* 0x50 - 0x5f */
+	"\r\000/";			/* 0x60 - 0x6f */
+
+unsigned char *k_sysrq_xlate = gen_sysrq_xlate;
+int k_sysrq_key = 0x54;
 #endif
diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c
--- a/arch/arm/mach-integrator/cpu.c	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/mach-integrator/cpu.c	Thu Aug  1 14:17:40 2002
@@ -1,9 +1,9 @@
 /*
  *  linux/arch/arm/mach-integrator/cpu.c
  *
- *  Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *  Copyright (C) 2001-2002 Deep Blue Solutions Ltd.
  *
- *  $Id: cpu.c,v 1.5 2002/07/06 16:53:17 rmk Exp $
+ *  $Id: cpu.c,v 1.6 2002/07/18 13:58:51 rmk Exp $
  *
  * 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
@@ -15,6 +15,9 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/cpufreq.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/init.h>
 
 #include <asm/hardware.h>
@@ -42,7 +45,7 @@
 
 #ifdef CONFIG_CPU_FREQ
 /*
- * Divisor indexes for in ascending divisor order
+ * Divisor indexes in ascending divisor order
  */
 static unsigned char s2od[] = { 1, 3, 4, 7, 5, 2, 6, 0 };
 
@@ -70,7 +73,8 @@
  * Validate the speed in khz.  If it is outside our
  * range, then return the lowest.
  */
-unsigned int integrator_validatespeed(unsigned int freq_khz)
+static unsigned int
+integrator_validatespeed(unsigned int cpu, unsigned int freq_khz)
 {
 	struct vco vco;
 
@@ -87,11 +91,21 @@
 	return vco_to_freq(vco, 1);
 }
 
-void integrator_setspeed(unsigned int freq_khz)
+static void integrator_setspeed(unsigned int cpu, unsigned int freq_khz)
 {
 	struct vco vco = freq_to_vco(freq_khz, 1);
+	unsigned long cpus_allowed;
 	u_int cm_osc;
 
+	/*
+	 * Save this threads cpus_allowed mask, and bind to the
+	 * specified CPU.  When this call returns, we should be
+	 * running on the right CPU.
+	 */
+	cpus_allowed = current->cpus_allowed;
+	set_cpus_allowed(current, 1 << cpu);
+	BUG_ON(cpu != smp_processor_id());
+
 	cm_osc = __raw_readl(CM_OSC);
 	cm_osc &= 0xfffff800;
 	cm_osc |= vco.vdw | vco.od << 8;
@@ -99,44 +113,72 @@
 	__raw_writel(0xa05f, CM_LOCK);
 	__raw_writel(cm_osc, CM_OSC);
 	__raw_writel(0, CM_LOCK);
+
+	/*
+	 * Restore the CPUs allowed mask.
+	 */
+	set_cpus_allowed(current, cpus_allowed);
 }
+
+static struct cpufreq_driver integrator_driver = {
+	.validate	= integrator_validatespeed,
+	.setspeed	= integrator_setspeed,
+	.sync		= 1,
+};
 #endif
 
-static int __init cpu_init(void)
+static int __init integrator_cpu_init(void)
 {
-	u_int cm_osc, cm_stat, cpu_freq_khz, mem_freq_khz;
-	struct vco vco;
+	struct cpufreq_freqs *freqs;
+	unsigned long cpus_allowed;
+	int cpu;
+
+	freqs = kmalloc(sizeof(struct cpufreq_freqs) * NR_CPUS,
+			GFP_KERNEL);
+	if (!freqs) {
+		printk(KERN_ERR "CPU: unable to allocate cpufreqs structure\n");
+		return -ENOMEM;
+	}
 
-	cm_osc = __raw_readl(CM_OSC);
+	cpus_allowed = current->cpus_allowed;
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		u_int cm_osc, cm_stat, mem_freq_khz;
+		struct vco vco;
+
+		if (!cpu_online(cpu))
+			continue;
+
+		set_cpus_allowed(current, 1 << cpu);
+		BUG_ON(cpu != smp_processor_id());
+
+		cm_stat = __raw_readl(CM_STAT);
+		cm_osc = __raw_readl(CM_OSC);
+		vco.od  = (cm_osc >> 20) & 7;
+		vco.vdw = (cm_osc >> 12) & 255;
+		mem_freq_khz = vco_to_freq(vco, 2);
+
+		printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255);
+		printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n",
+			cpu, mem_freq_khz / 1000, mem_freq_khz % 1000);
+
+		vco.od = (cm_osc >> 8) & 7;
+		vco.vdw = cm_osc & 255;
+
+		freqs[cpu].min = 12000;
+		freqs[cpu].max = 160000;
+		freqs[cpu].cur = vco_to_freq(vco, 1);
+	}
 
-	vco.od  = (cm_osc >> 20) & 7;
-	vco.vdw = (cm_osc >> 12) & 255;
-	mem_freq_khz = vco_to_freq(vco, 2);
-
-	printk(KERN_INFO "Memory clock = %d.%03d MHz\n",
-		mem_freq_khz / 1000, mem_freq_khz % 1000);
-
-	vco.od = (cm_osc >> 8) & 7;
-	vco.vdw = cm_osc & 255;
-	cpu_freq_khz = vco_to_freq(vco, 1);
+	set_cpus_allowed(current, cpus_allowed);
 
 #ifdef CONFIG_CPU_FREQ
-	{
-		struct cpufreq_driver cpufreq_driver;
-
-		cpufreq_driver.freq.min = 12000;
-		cpufreq_driver.freq.max = 160000;
-		cpufreq_driver.freq.cur = cpu_freq_khz;
-		cpufreq_driver.validate = &integrator_validatespeed;
-		cpufreq_driver.setspeed = &integrator_setspeed;
-		cpufreq_register(cpufreq_driver);
-	}
+	integrator_driver.freq = freqs;
+	cpufreq_register(&integrator_driver);
+#else
+	kfree(freqs);
 #endif
 
-	cm_stat = __raw_readl(CM_STAT);
-	printk("Module id: %d\n", cm_stat & 255);
-
 	return 0;
 }
 
-__initcall(cpu_init);
+__initcall(integrator_cpu_init);
diff -Nru a/arch/arm/mach-sa1100/adsbitsy.c b/arch/arm/mach-sa1100/adsbitsy.c
--- a/arch/arm/mach-sa1100/adsbitsy.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/adsbitsy.c	Thu Aug  1 14:17:36 2002
@@ -18,6 +18,7 @@
 #include <linux/serial_core.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
 
diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
--- a/arch/arm/mach-sa1100/assabet.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/assabet.c	Thu Aug  1 14:17:36 2002
@@ -20,6 +20,7 @@
 #include <linux/serial_core.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
 #include <asm/page.h>
diff -Nru a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
--- a/arch/arm/mach-sa1100/badge4.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/badge4.c	Thu Aug  1 14:17:36 2002
@@ -22,6 +22,7 @@
 #include <linux/errno.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/arch/irqs.h>
 
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c
--- a/arch/arm/mach-sa1100/cpu-sa1100.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c	Thu Aug  1 14:17:36 2002
@@ -91,7 +91,7 @@
 #include <asm/hardware.h>
 
 extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern unsigned int sa11x0_validatespeed(unsigned int khz);
+extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz);
 extern unsigned int sa11x0_getspeed(void);
 
 typedef struct {
@@ -220,29 +220,35 @@
 };
 
 
-static void sa1100_setspeed(unsigned int khz)
+static void sa1100_setspeed(unsigned int cpu, unsigned int khz)
 {
 	PPCR = sa11x0_freq_to_ppcr(khz);
 }
 
+static struct cpufreq_freqs sa1100_freqs = {
+	.min		= 59000,
+	.max		= 287000,
+};
+
+static struct cpufreq_driver sa1100_driver = {
+	.freq		= &sa1100_freqs,
+	.validate	= sa11x0_validatespeed,
+	.setspeed	= sa1100_setspeed,
+	.sync		= 1,
+};
+
 static int __init sa1100_dram_init(void)
 {
 	int ret = -ENODEV;
 
 	if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) {
-		cpufreq_driver_t cpufreq_driver;
-
 		ret = cpufreq_register_notifier(&sa1100_dram_block);
 		if (ret)
 			return ret;
 
-		cpufreq_driver.freq.min = 59000;
-		cpufreq_driver.freq.max = 287000;
-		cpufreq_driver.freq.cur = sa11x0_getspeed();
-		cpufreq_driver.validate = &sa11x0_validatespeed;
-		cpufreq_driver.setspeed = &sa1100_setspeed;
+		sa1100_freqs.cur = sa11x0_getspeed();
 
-		ret = cpufreq_register(cpufreq_driver);<
+		ret = cpufreq_register(&sa1100_driver);
 	}
 
 	return ret;
diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c
--- a/arch/arm/mach-sa1100/cpu-sa1110.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	Thu Aug  1 14:17:36 2002
@@ -24,13 +24,14 @@
 #include <linux/init.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
 #undef DEBUG
 
 extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz);
-extern unsigned int sa11x0_validatespeed(unsigned int khz);
+extern unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz);
 extern unsigned int sa11x0_getspeed(void);
 
 struct sdram_params {
@@ -213,7 +214,7 @@
  * above, we can match for an exact frequency.  If we don't find
  * an exact match, we will to set the lowest frequency to be safe.
  */
-static void sa1110_setspeed(unsigned int khz)
+static void sa1110_setspeed(unsigned int cpu, unsigned int khz)
 {
 	struct sdram_params *sdram = &sdram_params;
 	struct sdram_info sd;
@@ -284,6 +285,18 @@
 	sdram_update_refresh(khz, sdram);
 }
 
+static struct cpufreq_freqs sa1110_freqs = {
+	.min		= 59000,
+	.max		= 287000,
+};
+
+static struct cpufreq_driver sa1110_driver = {
+	.freq		= &sa1110_freqs,
+	.validate	= sa11x0_validatespeed,
+	.setspeed	= sa1110_setspeed,
+	.sync		= 1,
+};
+
 static int __init sa1110_clk_init(void)
 {
 	struct sdram_params *sdram = NULL;
@@ -298,8 +311,6 @@
 		sdram = &samsung_km416s4030ct;
 
 	if (sdram) {
-		struct cpufreq_driver cpufreq_driver;
-
 		printk(KERN_DEBUG "SDRAM: tck: %d trcd: %d trp: %d"
 			" twr: %d refresh: %d cas_latency: %d\n",
 			sdram->tck, sdram->trcd, sdram->trp,
@@ -307,15 +318,10 @@
 
 		memcpy(&sdram_params, sdram, sizeof(sdram_params));
 
-		sa1110_setspeed(sa11x0_getspeed());
-
-		cpufreq_driver.freq.min = 59000;
-		cpufreq_driver.freq.max = 287000;
-		cpufreq_driver.freq.cur = sa11x0_getspeed();
-		cpufreq_driver.validate = &sa11x0_validatespeed;
-		cpufreq_driver.setspeed = &sa1110_setspeed;
+		sa1110_freqs.cur = sa11x0_getspeed();
+		sa1110_setspeed(0, sa1110_freqs.cur);
 
-		return cpufreq_register(cpufreq_driver);
+		return cpufreq_register(&sa1110_driver);
 	}
 
 	return 0;
diff -Nru a/arch/arm/mach-sa1100/freebird.c b/arch/arm/mach-sa1100/freebird.c
--- a/arch/arm/mach-sa1100/freebird.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/freebird.c	Thu Aug  1 14:17:36 2002
@@ -9,6 +9,7 @@
 #include <linux/tty.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
--- a/arch/arm/mach-sa1100/generic.c	Thu Aug  1 14:17:39 2002
+++ b/arch/arm/mach-sa1100/generic.c	Thu Aug  1 14:17:39 2002
@@ -71,7 +71,7 @@
  * Validate the speed in khz.  If we can't generate the precise
  * frequency requested, round it down (to be on the safe side).
  */
-unsigned int sa11x0_validatespeed(unsigned int khz)
+unsigned int sa11x0_validatespeed(unsigned int cpu, unsigned int khz)
 {
 	return cclk_frequency_100khz[sa11x0_freq_to_ppcr(khz)] * 100;
 }
diff -Nru a/arch/arm/mach-sa1100/graphicsmaster.c b/arch/arm/mach-sa1100/graphicsmaster.c
--- a/arch/arm/mach-sa1100/graphicsmaster.c	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/mach-sa1100/graphicsmaster.c	Thu Aug  1 14:17:40 2002
@@ -15,6 +15,7 @@
 #include <linux/ioport.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 #include <asm/irq.h>
 
diff -Nru a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
--- a/arch/arm/mach-sa1100/h3600.c	Thu Aug  1 14:17:37 2002
+++ b/arch/arm/mach-sa1100/h3600.c	Thu Aug  1 14:17:37 2002
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mach-sa1100/huw_webpanel.c b/arch/arm/mach-sa1100/huw_webpanel.c
--- a/arch/arm/mach-sa1100/huw_webpanel.c	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/mach-sa1100/huw_webpanel.c	Thu Aug  1 14:17:40 2002
@@ -8,6 +8,7 @@
 #include <linux/tty.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
--- a/arch/arm/mach-sa1100/neponset.c	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/mach-sa1100/neponset.c	Thu Aug  1 14:17:40 2002
@@ -13,6 +13,7 @@
 #include <linux/device.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/irq.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-sa1100/omnimeter.c b/arch/arm/mach-sa1100/omnimeter.c
--- a/arch/arm/mach-sa1100/omnimeter.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/omnimeter.c	Thu Aug  1 14:17:36 2002
@@ -7,6 +7,7 @@
 #include <linux/tty.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mach-sa1100/pfs168.c b/arch/arm/mach-sa1100/pfs168.c
--- a/arch/arm/mach-sa1100/pfs168.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/pfs168.c	Thu Aug  1 14:17:36 2002
@@ -9,6 +9,7 @@
 #include <linux/ioport.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mach-sa1100/sa1111.c b/arch/arm/mach-sa1100/sa1111.c
--- a/arch/arm/mach-sa1100/sa1111.c	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/mach-sa1100/sa1111.c	Thu Aug  1 14:17:40 2002
@@ -27,6 +27,7 @@
 #include <linux/slab.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c
--- a/arch/arm/mach-sa1100/system3.c	Thu Aug  1 14:17:41 2002
+++ b/arch/arm/mach-sa1100/system3.c	Thu Aug  1 14:17:41 2002
@@ -44,9 +44,8 @@
 #include <linux/cpufreq.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
 #include <asm/irq.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mach-sa1100/yopy.c b/arch/arm/mach-sa1100/yopy.c
--- a/arch/arm/mach-sa1100/yopy.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mach-sa1100/yopy.c	Thu Aug  1 14:17:36 2002
@@ -7,6 +7,7 @@
 #include <linux/tty.h>
 
 #include <asm/hardware.h>
+#include <asm/mach-types.h>
 #include <asm/setup.h>
 
 #include <asm/mach/arch.h>
diff -Nru a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
--- a/arch/arm/mm/alignment.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mm/alignment.c	Thu Aug  1 14:17:36 2002
@@ -399,13 +399,13 @@
 		eaddr += 4;
 
 	/* 
-	 * For alignment faults on the ARM922T the MMU  makes 
+	 * For alignment faults on the ARM922T/ARM920T the MMU  makes
 	 * the FSR (and hence addr) equal to the updated base address
 	 * of the multiple access rather than the restored value.
-	 * Switch this messsage off if we've got a ARM922, otherwise
+	 * Switch this messsage off if we've got a ARM92[02], otherwise
 	 * [ls]dm alignment faults are noisy!
 	 */
-#if !(defined CONFIG_CPU_ARM922T)  
+#if !(defined CONFIG_CPU_ARM922T)  && !(defined CONFIG_CPU_ARM920T)
 	/*
 	 * This is a "hint" - we already have eaddr worked out by the
 	 * processor for us.
diff -Nru a/arch/arm/mm/init.c b/arch/arm/mm/init.c
--- a/arch/arm/mm/init.c	Thu Aug  1 14:17:36 2002
+++ b/arch/arm/mm/init.c	Thu Aug  1 14:17:36 2002
@@ -18,7 +18,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
diff -Nru a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
--- a/arch/arm/mm/mm-armv.c	Thu Aug  1 14:17:41 2002
+++ b/arch/arm/mm/mm-armv.c	Thu Aug  1 14:17:41 2002
@@ -17,6 +17,7 @@
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/page.h>
+#include <asm/rmap.h>
 #include <asm/io.h>
 #include <asm/setup.h>
 
@@ -149,6 +150,7 @@
 
 	pte = pmd_page(*pmd);
 	pmd_clear(pmd);
+	pgtable_remove_rmap(pte);
 	pte_free(pte);
 	pmd_free(pmd);
 free:
diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types	Thu Aug  1 14:17:40 2002
+++ b/arch/arm/tools/mach-types	Thu Aug  1 14:17:40 2002
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Fri Jul 5 21:32:20 2002
+# Last update: Sat Jul 27 09:56:53 2002
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -175,7 +175,7 @@
 iam			SA1100_IAM		IAM			164
 tt530			SA1100_TT530		TT530			165
 sam2400			ARCH_SAM2400		SAM2400			166
-jornada56x		ARCH_JORNADA56X		JORNADA56X		167
+jornada56x		SA1100_JORNADA56X	JORNADA56X		167
 active			SA1100_ACTIVE		ACTIVE			168
 iq80321			ARCH_IQ80321		IQ80321			169
 wid			SA1100_WID		WID			170
@@ -207,3 +207,10 @@
 bitbox			SA1100_BITBOX		BITBOX			196
 g200			SA1100_G200		G200			197
 gill			SA1100_GILL		GILL			198
+pxa_mercury		ARCH_PXA_MERCURY	PXA_MERCURY		199
+ceiva			ARCH_CEIVA		CEIVA			200
+fret			SA1100_FRET		FRET			201
+emailphone		SA1100_EMAILPHONE	EMAILPHONE		202
+h3900			ARCH_H3900		H3900			203
+pxa1			ARCH_PXA1		PXA1			204
+koan369			SA1100_KOAN369		KOAN369			205
diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
--- a/arch/i386/kernel/Makefile	Thu Aug  1 14:17:36 2002
+++ b/arch/i386/kernel/Makefile	Thu Aug  1 14:17:36 2002
@@ -6,7 +6,7 @@
 
 O_TARGET := kernel.o
 
-export-objs     := mca.o mtrr.o msr.o cpuid.o microcode.o i386_ksyms.o time.o
+export-objs     := mca.o mtrr.o i386_ksyms.o time.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o vm86.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_i386.o \
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
--- a/arch/i386/kernel/apic.c	Thu Aug  1 14:17:41 2002
+++ b/arch/i386/kernel/apic.c	Thu Aug  1 14:17:41 2002
@@ -1140,7 +1140,7 @@
 	   6: Received illegal vector
 	   7: Illegal register address
 	*/
-	printk (KERN_ERR "APIC error on CPU%d: %02lx(%02lx)\n",
+	printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n",
 	        smp_processor_id(), v , v1);
 	irq_exit();
 }
diff -Nru a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c	Thu Aug  1 14:17:36 2002
+++ b/arch/i386/kernel/apm.c	Thu Aug  1 14:17:36 2002
@@ -1589,7 +1589,7 @@
 
 	p = buf;
 
-	if ((num_possible_cpus() == 1) &&
+	if ((num_online_cpus() == 1) &&
 	    !(error = apm_get_power_status(&bx, &cx, &dx))) {
 		ac_line_status = (bx >> 8) & 0xff;
 		battery_status = bx & 0xff;
@@ -1720,7 +1720,7 @@
 		}
 	}
 
-	if (debug && (num_possible_cpus() == 1)) {
+	if (debug && (num_online_cpus() == 1)) {
 		error = apm_get_power_status(&bx, &cx, &dx);
 		if (error)
 			printk(KERN_INFO "apm: power status not available\n");
@@ -1764,7 +1764,7 @@
 		pm_power_off = apm_power_off;
 	register_sysrq_key('o', &sysrq_poweroff_op);
 
-	if (num_possible_cpus() == 1) {
+	if (num_online_cpus() == 1) {
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 		console_blank_hook = apm_console_blank;
 #endif
@@ -1853,6 +1853,7 @@
 static int __init apm_init(void)
 {
 	struct proc_dir_entry *apm_proc;
+	int i;
 
 	if (apm_info.bios.version == 0) {
 		printk(KERN_INFO "apm: BIOS not found.\n");
@@ -1907,7 +1908,7 @@
 		printk(KERN_NOTICE "apm: disabled on user request.\n");
 		return -ENODEV;
 	}
-	if ((num_possible_cpus() > 1) && !power_off) {
+	if ((num_online_cpus() > 1) && !power_off) {
 		printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
 		return -ENODEV;
 	}
@@ -1926,37 +1927,39 @@
 	 * NOTE: on SMP we call into the APM BIOS only on CPU#0, so it's
 	 * enough to modify CPU#0's GDT.
 	 */
-	set_base(cpu_gdt_table[0][APM_40 >> 3],
-		 __va((unsigned long)0x40 << 4));
-	_set_limit((char *)&cpu_gdt_table[0][APM_40 >> 3], 4095 - (0x40 << 4));
-
-	apm_bios_entry.offset = apm_info.bios.offset;
-	apm_bios_entry.segment = APM_CS;
-	set_base(cpu_gdt_table[0][APM_CS >> 3],
-		 __va((unsigned long)apm_info.bios.cseg << 4));
-	set_base(cpu_gdt_table[0][APM_CS_16 >> 3],
-		 __va((unsigned long)apm_info.bios.cseg_16 << 4));
-	set_base(cpu_gdt_table[0][APM_DS >> 3],
-		 __va((unsigned long)apm_info.bios.dseg << 4));
+	for (i = 0; i < NR_CPUS; i++) {
+		set_base(cpu_gdt_table[i][APM_40 >> 3],
+			 __va((unsigned long)0x40 << 4));
+		_set_limit((char *)&cpu_gdt_table[i][APM_40 >> 3], 4095 - (0x40 << 4));
+
+		apm_bios_entry.offset = apm_info.bios.offset;
+		apm_bios_entry.segment = APM_CS;
+		set_base(cpu_gdt_table[i][APM_CS >> 3],
+			 __va((unsigned long)apm_info.bios.cseg << 4));
+		set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
+			 __va((unsigned long)apm_info.bios.cseg_16 << 4));
+		set_base(cpu_gdt_table[i][APM_DS >> 3],
+			 __va((unsigned long)apm_info.bios.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
-	if (apm_info.bios.version == 0x100) {
+		if (apm_info.bios.version == 0x100) {
 #endif
-		/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
-		_set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3], 64 * 1024 - 1);
-		/* For some unknown machine. */
-		_set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3], 64 * 1024 - 1);
-		/* For the DEC Hinote Ultra CT475 (and others?) */
-		_set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3], 64 * 1024 - 1);
+			/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1);
+			/* For some unknown machine. */
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1);
+			/* For the DEC Hinote Ultra CT475 (and others?) */
+			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1);
 #ifndef APM_RELAX_SEGMENTS
-	} else {
-		_set_limit((char *)&cpu_gdt_table[0][APM_CS >> 3],
-			(apm_info.bios.cseg_len - 1) & 0xffff);
-		_set_limit((char *)&cpu_gdt_table[0][APM_CS_16 >> 3],
-			(apm_info.bios.cseg_16_len - 1) & 0xffff);
-		_set_limit((char *)&cpu_gdt_table[0][APM_DS >> 3],
-			(apm_info.bios.dseg_len - 1) & 0xffff);
-	}
+		} else {
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3],
+				(apm_info.bios.cseg_len - 1) & 0xffff);
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3],
+				(apm_info.bios.cseg_16_len - 1) & 0xffff);
+			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3],
+				(apm_info.bios.dseg_len - 1) & 0xffff);
+		}
 #endif
+	}
 
 	apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info);
 	if (apm_proc)
@@ -1964,7 +1967,7 @@
 
 	kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
 
-	if (num_possible_cpus() > 1) {
+	if (num_online_cpus() > 1) {
 		printk(KERN_NOTICE
 		   "apm: disabled - APM is not SMP safe (power off active).\n");
 		return 0;
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	Thu Aug  1 14:17:39 2002
+++ b/arch/i386/kernel/entry.S	Thu Aug  1 14:17:39 2002
@@ -689,8 +689,8 @@
 	.long sys_rt_sigtimedwait
 	.long sys_rt_sigqueueinfo
 	.long sys_rt_sigsuspend
-	.long sys_pread		/* 180 */
-	.long sys_pwrite
+	.long sys_pread64	/* 180 */
+	.long sys_pwrite64
 	.long sys_chown16
 	.long sys_getcwd
 	.long sys_capget
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	Thu Aug  1 14:17:40 2002
+++ b/arch/i386/kernel/i386_ksyms.c	Thu Aug  1 14:17:40 2002
@@ -132,6 +132,7 @@
 EXPORT_SYMBOL_NOVERS(__read_lock_failed);
 
 /* Global SMP stuff */
+EXPORT_SYMBOL(synchronize_irq);
 EXPORT_SYMBOL(smp_call_function);
 
 /* TLB flushing */
diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	Thu Aug  1 14:17:41 2002
+++ b/arch/i386/kernel/i8259.c	Thu Aug  1 14:17:41 2002
@@ -38,7 +38,8 @@
 
 static void end_8259A_irq (unsigned int irq)
 {
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) &&
+							irq_desc[irq].action)
 		enable_8259A_irq(irq);
 }
 
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
--- a/arch/i386/kernel/io_apic.c	Thu Aug  1 14:17:40 2002
+++ b/arch/i386/kernel/io_apic.c	Thu Aug  1 14:17:40 2002
@@ -791,7 +791,7 @@
 	entry.vector = vector;
 
 	/*
-	 * The timer IRQ doesnt have to know that behind the
+	 * The timer IRQ doesn't have to know that behind the
 	 * scene we have a 8259A-master in AEOI mode ...
 	 */
 	irq_desc[0].handler = &ioapic_edge_irq_type;
@@ -1654,7 +1654,7 @@
 	printk(" failed.\n");
 
 	if (nmi_watchdog) {
-		printk(KERN_WARNING "timer doesnt work through the IO-APIC - disabling NMI Watchdog!\n");
+		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
 		nmi_watchdog = 0;
 	}
 
diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Thu Aug  1 14:17:36 2002
+++ b/arch/i386/kernel/irq.c	Thu Aug  1 14:17:36 2002
@@ -187,10 +187,6 @@
 #if CONFIG_SMP
 inline void synchronize_irq(unsigned int irq)
 {
-	/* is there anything to synchronize with? */
-	if (!irq_desc[irq].action)
-		return;
-
 	while (irq_desc[irq].status & IRQ_INPROGRESS)
 		cpu_relax();
 }
@@ -350,7 +346,7 @@
 	 * use the action we have.
 	 */
 	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+	if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
 		action = desc->action;
 		status &= ~IRQ_PENDING; /* we commit to handling */
 		status |= IRQ_INPROGRESS; /* we are handling it */
@@ -363,7 +359,7 @@
 	   a different instance of this same irq, the other processor
 	   will take care of it.
 	 */
-	if (!action)
+	if (unlikely(!action))
 		goto out;
 
 	/*
@@ -381,12 +377,12 @@
 		handle_IRQ_event(irq, &regs, action);
 		spin_lock(&desc->lock);
 		
-		if (!(desc->status & IRQ_PENDING))
+		if (likely(!(desc->status & IRQ_PENDING)))
 			break;
 		desc->status &= ~IRQ_PENDING;
 	}
-	desc->status &= ~IRQ_INPROGRESS;
 out:
+	desc->status &= ~IRQ_INPROGRESS;
 	/*
 	 * The ->end() handler has to deal with interrupts which got
 	 * disabled while the handler was running.
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	Thu Aug  1 14:17:36 2002
+++ b/arch/i386/kernel/process.c	Thu Aug  1 14:17:36 2002
@@ -476,32 +476,42 @@
 }
 
 /*
+ * This gets run with %ebx containing the
+ * function to call, and %edx containing
+ * the "args".
+ */
+extern void kernel_thread_helper(void);
+__asm__(".align 4\n"
+	"kernel_thread_helper:\n\t"
+	"movl %edx,%eax\n\t"
+	"pushl %edx\n\t"
+	"call *%ebx\n\t"
+	"pushl %eax\n\t"
+	"call do_exit");
+
+/*
  * Create a kernel thread
  */
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
-	long retval, d0;
+	struct task_struct *p;
+	struct pt_regs regs;
 
-	__asm__ __volatile__(
-		"movl %%esp,%%esi\n\t"
-		"int $0x80\n\t"		/* Linux/i386 system call */
-		"cmpl %%esp,%%esi\n\t"	/* child or parent? */
-		"je 1f\n\t"		/* parent - jump */
-		/* Load the argument into eax, and push it.  That way, it does
-		 * not matter whether the called function is compiled with
-		 * -mregparm or not.  */
-		"movl %4,%%eax\n\t"
-		"pushl %%eax\n\t"		
-		"call *%5\n\t"		/* call fn */
-		"movl %3,%0\n\t"	/* exit */
-		"int $0x80\n"
-		"1:\t"
-		:"=&a" (retval), "=&S" (d0)
-		:"0" (__NR_clone), "i" (__NR_exit),
-		 "r" (arg), "r" (fn),
-		 "b" (flags | CLONE_VM)
-		: "memory");
-	return retval;
+	memset(&regs, 0, sizeof(regs));
+
+	regs.ebx = (unsigned long) fn;
+	regs.edx = (unsigned long) arg;
+
+	regs.xds = __KERNEL_DS;
+	regs.xes = __KERNEL_DS;
+	regs.orig_eax = -1;
+	regs.eip = (unsigned long) kernel_thread_helper;
+	regs.xcs = __KERNEL_CS;
+	regs.eflags = 0x286;
+
+	/* Ok, create the new process.. */
+	p = do_fork(flags | CLONE_VM, 0, &regs, 0);
+	return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
 /*
@@ -675,6 +685,14 @@
 	tss->esp0 = next->esp0;
 
 	/*
+	 * Load the per-thread Thread-Local Storage descriptor.
+	 *
+	 * NOTE: it's faster to do the two stores unconditionally
+	 * than to branch away.
+	 */
+	load_TLS_desc(next, cpu);
+
+	/*
 	 * Save away %fs and %gs. No need to save %es and %ds, as
 	 * those are always kernel segments while inside the kernel.
 	 */
@@ -690,14 +708,6 @@
 	}
 
 	/*
-	 * Load the per-thread Thread-Local Storage descriptor.
-	 *
-	 * NOTE: it's faster to do the two stores unconditionally
-	 * than to branch away.
-	 */
-	load_TLS_desc(next, cpu);
-
-	/*
 	 * Now maybe reload the debug registers
 	 */
 	if (unlikely(next->debugreg[7])) {
@@ -831,34 +841,16 @@
 /*
  * Set the Thread-Local Storage area:
  */
-asmlinkage int sys_set_thread_area(unsigned int base, unsigned int limit, unsigned int flags)
+asmlinkage int sys_set_thread_area(unsigned long base, unsigned long flags)
 {
 	struct thread_struct *t = &current->thread;
-	int limit_in_pages = 0, writable = 0;
+	int writable = 0;
 	int cpu;
 
 	/* do not allow unused flags */
 	if (flags & ~TLS_FLAGS_MASK)
 		return -EINVAL;
 
-	/* check limit */
-	if (limit & 0xfff00000)
-		return -EINVAL;
-
-	/*
-	 * Clear the TLS?
-	 */
-	if (flags & TLS_FLAG_CLEAR) {
-		cpu = get_cpu();
-		t->tls_base = t->tls_limit = t->tls_flags = 0;
-        	t->tls_desc.a = t->tls_desc.b = 0;
-		load_TLS_desc(t, cpu);
-		put_cpu();
-		return 0;
-	}
-
-	if (flags & TLS_FLAG_LIMIT_IN_PAGES)
-		limit_in_pages = 1;
 	if (flags & TLS_FLAG_WRITABLE)
 		writable = 1;
 
@@ -866,15 +858,12 @@
 	 * We must not get preempted while modifying the TLS.
 	 */
 	cpu = get_cpu();
-	t->tls_base = base;
-	t->tls_limit = limit;
-	t->tls_flags = flags;
 
-        t->tls_desc.a = ((base & 0x0000ffff) << 16) | (limit & 0x0ffff);
+        t->tls_desc.a = ((base & 0x0000ffff) << 16) | 0xffff;
 
         t->tls_desc.b = (base & 0xff000000) | ((base & 0x00ff0000) >> 16) |
-                  (limit & 0xf0000) | (writable << 9) | (1 << 15) |
-		  (1 << 22) | (limit_in_pages << 23) | 0x7000;
+				0xf0000 | (writable << 9) | (1 << 15) |
+					(1 << 22) | (1 << 23) | 0x7000;
 
 	load_TLS_desc(t, cpu);
 	put_cpu();
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Thu Aug  1 14:17:37 2002
+++ b/arch/i386/mm/init.c	Thu Aug  1 14:17:37 2002
@@ -54,7 +54,7 @@
 		
 #if CONFIG_X86_PAE
 	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-	set_pgd(pgd, __pgd(__pa(md_table) | _PAGE_PRESENT));
+	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
 	if (pmd_table != pmd_offset(pgd, 0)) 
 		BUG();
 #else
diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in
--- a/arch/ia64/config.in	Thu Aug  1 14:17:41 2002
+++ b/arch/ia64/config.in	Thu Aug  1 14:17:41 2002
@@ -71,15 +71,15 @@
 
 if [ "$CONFIG_IA64_SGI_SN1" = "y" -o  "$CONFIG_IA64_SGI_SN2" = "y" ]; then
 	define_bool CONFIG_IA64_SGI_SN y
-	bool '  Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG n
+	bool '  Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG
 	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
 	bool '  Enable autotest (llsc). Option to run cache test instead of booting' \
-			CONFIG_IA64_SGI_AUTOTEST n
+			CONFIG_IA64_SGI_AUTOTEST
 	define_bool CONFIG_DEVFS_FS y
 	if [ "$CONFIG_DEVFS_FS" = "y" ]; then
-	  bool '    Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG n
+	  bool '    Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG
 	fi
-	bool '  Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL y
+	bool '  Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL
 	define_bool CONFIG_DISCONTIGMEM y
 	define_bool CONFIG_IA64_MCA y
 	define_bool CONFIG_NUMA y
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	Thu Aug  1 14:17:41 2002
+++ b/arch/ia64/ia32/sys_ia32.c	Thu Aug  1 14:17:41 2002
@@ -3648,15 +3648,15 @@
 asmlinkage long
 sys32_pread (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
-	extern asmlinkage long sys_pread (unsigned int, char *, size_t, loff_t);
-	return sys_pread(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
+	extern asmlinkage long sys_pread64 (unsigned int, char *, size_t, loff_t);
+	return sys_pread64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
 sys32_pwrite (unsigned int fd, void *buf, unsigned int count, u32 pos_lo, u32 pos_hi)
 {
-	extern asmlinkage long sys_pwrite (unsigned int, const char *, size_t, loff_t);
-	return sys_pwrite(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
+	extern asmlinkage long sys_pwrite64 (unsigned int, const char *, size_t, loff_t);
+	return sys_pwrite64(fd, buf, count, ((unsigned long) pos_hi << 32) | pos_lo);
 }
 
 asmlinkage long
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Thu Aug  1 14:17:39 2002
+++ b/arch/ia64/kernel/entry.S	Thu Aug  1 14:17:39 2002
@@ -1134,8 +1134,8 @@
 	data8 sys_flock				// 1145
 	data8 sys_readv
 	data8 sys_writev
-	data8 sys_pread
-	data8 sys_pwrite
+	data8 sys_pread64
+	data8 sys_pwrite64
 	data8 sys_sysctl			// 1150
 	data8 sys_mmap
 	data8 sys_munmap
diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
--- a/arch/ia64/lib/Makefile	Thu Aug  1 14:17:41 2002
+++ b/arch/ia64/lib/Makefile	Thu Aug  1 14:17:41 2002
@@ -4,7 +4,7 @@
 
 L_TARGET = lib.a
 
-export-objs := io.o swiotlb.o
+export-objs := swiotlb.o
 
 obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o					\
 	__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o					\
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Thu Aug  1 14:17:40 2002
+++ b/arch/ia64/mm/init.c	Thu Aug  1 14:17:40 2002
@@ -167,10 +167,10 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 	{
-		pg_data_t *pgdat = pgdat_list;
+		pg_data_t *pgdat;
 
 		printk("Free swap:       %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
-		do {
+		for_each_pgdat(pgdat) {
 			printk("Node ID: %d\n", pgdat->node_id);
 			for(i = 0; i < pgdat->node_size; i++) {
 				if (PageReserved(pgdat->node_mem_map+i))
@@ -184,8 +184,7 @@
 			printk("\t%d reserved pages\n", reserved);
 			printk("\t%d pages shared\n", shared);
 			printk("\t%d pages swap cached\n", cached);
-			pgdat = pgdat->node_next;
-		} while (pgdat);
+		}
 		printk("Total of %ld pages in page table cache\n", pgtable_cache_size);
 		printk("%d free buffer pages\n", nr_free_buffer_pages());
 	}
diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile
--- a/arch/ia64/sn/io/Makefile	Thu Aug  1 14:17:39 2002
+++ b/arch/ia64/sn/io/Makefile	Thu Aug  1 14:17:39 2002
@@ -18,7 +18,7 @@
 O_TARGET := sgiio.o
 
 ifeq ($(CONFIG_MODULES),y)
-export-objs = pciio.o hcl.o pci_dma.o
+export-objs = pciio.o hcl.o
 endif
 
 obj-y  := stubs.o sgi_if.o pciio.o xtalk.o xbow.o xswitch.o klgraph_hack.o \
diff -Nru a/arch/ia64/sn/io/hcl.c b/arch/ia64/sn/io/hcl.c
--- a/arch/ia64/sn/io/hcl.c	Thu Aug  1 14:17:39 2002
+++ b/arch/ia64/sn/io/hcl.c	Thu Aug  1 14:17:39 2002
@@ -673,8 +673,9 @@
 		 * Call devfs to get the devfs entry.
 		 */
 		namelen = (int) strlen(name);
-		target_handle = devfs_find_handle (from, name, 0, 0,
+		target_handle = devfs_get_handle(from, name, 0, 0,
 					0, 1); /* Yes traverse symbolic links */
+		devfs_put(target_handle); /* Assume we're the owner */
 		if (target_handle == NULL)
 			return(-1);
 		else
@@ -952,12 +953,13 @@
 			devfs_handle_t *vertex_handle_ptr,
 			char **remainder)
 {
-	*vertex_handle_ptr = devfs_find_handle(start_vertex_handle,	/* start dir */
+	*vertex_handle_ptr = devfs_get_handle(start_vertex_handle,	/* start dir */
 					lookup_path,		/* path */
 					0,			/* major */
 					0,			/* minor */
 					0,			/* char | block */
 					1);			/* traverse symlinks */
+	devfs_put(*vertex_handle_ptr); /* Assume we're the owner */
 	if (*vertex_handle_ptr == NULL)
 		return(-1);
 	else
@@ -965,22 +967,23 @@
 }
 
 /*
- * hwgraph_traverse - Find and return the devfs handle starting from de.
+ * hwgraph_traverse - Find and return the devfs handle starting from dir.
  *
  */
 graph_error_t
-hwgraph_traverse(devfs_handle_t de, char *path, devfs_handle_t *found)
+hwgraph_traverse(devfs_handle_t dir, char *path, devfs_handle_t *found)
 {
 	/* 
 	 * get the directory entry (path should end in a directory)
 	 */
 
-	*found = devfs_find_handle(de,	/* start dir */
+	*found = devfs_get_handle(dir,	/* start dir */
 			    path,	/* path */
 			    0,		/* major */
 			    0,		/* minor */
 			    0,		/* char | block */
 			    1);		/* traverse symlinks */
+	devfs_put(*found); /* Assume we're the owner */
 	if (*found == NULL)
 		return(GRAPH_NOT_FOUND);
 	else
@@ -994,12 +997,16 @@
 devfs_handle_t
 hwgraph_path_to_vertex(char *path)
 {
-	return(devfs_find_handle(NULL,	/* start dir */
+	devfs_handle_t de;
+
+	de = devfs_get_handle(NULL,	/* start dir */
 			path,		/* path */
 		    	0,		/* major */
 		    	0,		/* minor */
 		    	0,		/* char | block */
-		    	1));		/* traverse symlinks */
+		    	1);
+	devfs_put(de); /* Assume we're the owner */
+	return(de);
 }
 
 /*
@@ -1017,32 +1024,40 @@
 
 /*
  * hwgraph_block_device_get - return the handle of the block device file.
- *	The assumption here is that de is a directory.
+ *	The assumption here is that dir is a directory.
 */
 devfs_handle_t
-hwgraph_block_device_get(devfs_handle_t de)
+hwgraph_block_device_get(devfs_handle_t dir)
 {
-	return(devfs_find_handle(de,		/* start dir */
+	devfs_handle_t de;
+
+	de = devfs_get_handle(dir,		/* start dir */
 			"block",		/* path */
 		    	0,			/* major */
 		    	0,			/* minor */
 		    	DEVFS_SPECIAL_BLK,	/* char | block */
-		    	1));			/* traverse symlinks */
+		    	1);			/* traverse symlinks */
+	devfs_put(de); /* Assume we're the owner */
+	return(de);
 }
 
 /*
  * hwgraph_char_device_get - return the handle of the char device file.
- *      The assumption here is that de is a directory.
+ *      The assumption here is that dir is a directory.
 */
 devfs_handle_t
-hwgraph_char_device_get(devfs_handle_t de)
+hwgraph_char_device_get(devfs_handle_t dir)
 {
-	return(devfs_find_handle(de,		/* start dir */
+	devfs_handle_t de;
+
+	de = devfs_get_handle(dir,		/* start dir */
 			"char",			/* path */
 		    	0,			/* major */
 		    	0,			/* minor */
 		    	DEVFS_SPECIAL_CHR,	/* char | block */
-		    	1));			/* traverse symlinks */
+		    	1);			/* traverse symlinks */
+	devfs_put(de); /* Assume we're the owner */
+	return(de);
 }
 
 /*
diff -Nru a/arch/m68k/atari/joystick.c b/arch/m68k/atari/joystick.c
--- a/arch/m68k/atari/joystick.c	Thu Aug  1 14:17:36 2002
+++ b/arch/m68k/atari/joystick.c	Thu Aug  1 14:17:36 2002
@@ -134,7 +134,7 @@
     init_waitqueue_head(&joystick[0].wait);
     init_waitqueue_head(&joystick[1].wait);
 
-    if (devfs_register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
+    if (register_chrdev(MAJOR_NR, "Joystick", &atari_joystick_fops))
 	printk("unable to get major %d for joystick devices\n", MAJOR_NR);
     devfs_register_series (NULL, "joysticks/digital%u", 2, DEVFS_FL_DEFAULT,
 			   MAJOR_NR, 128, S_IFCHR | S_IRUSR | S_IWUSR,
diff -Nru a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
--- a/arch/m68k/kernel/entry.S	Thu Aug  1 14:17:36 2002
+++ b/arch/m68k/kernel/entry.S	Thu Aug  1 14:17:36 2002
@@ -608,8 +608,8 @@
 	.long sys_rt_sigtimedwait
 	.long sys_rt_sigqueueinfo
 	.long sys_rt_sigsuspend
-	.long sys_pread		/* 180 */
-	.long sys_pwrite
+	.long sys_pread64	/* 180 */
+	.long sys_pwrite64
 	.long sys_lchown16;
 	.long sys_getcwd
 	.long sys_capget
diff -Nru a/arch/mips/baget/Makefile b/arch/mips/baget/Makefile
--- a/arch/mips/baget/Makefile	Thu Aug  1 14:17:41 2002
+++ b/arch/mips/baget/Makefile	Thu Aug  1 14:17:41 2002
@@ -5,7 +5,7 @@
 
 O_TARGET := baget.a
 
-export-objs		:= vacserial.o vacrtc.o
+export-objs		:= vacserial.o
 obj-y			:= baget.o print.o setup.o time.o irq.o bagetIRQ.o \
 			   reset.o wbflush.o
 obj-$(CONFIG_SERIAL)	+= vacserial.o
diff -Nru a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
--- a/arch/mips/kernel/Makefile	Thu Aug  1 14:17:40 2002
+++ b/arch/mips/kernel/Makefile	Thu Aug  1 14:17:40 2002
@@ -6,6 +6,7 @@
 
 O_TARGET	:= kernel.o
 EXTRA_TARGETS	:= head.o init_task.o
+export-objs	:= mips_ksyms.o
 
 obj-y				+= branch.o process.o signal.o entry.o \
 				   traps.o ptrace.o vm86.o ioport.o reset.o \
@@ -27,14 +28,12 @@
 obj-$(CONFIG_SMP)		+= smp.o
 
 # Old style irq support, going to die in 2.5.
-export-objs			+= old-irq.o
 obj-$(CONFIG_NEW_IRQ)		+= irq.o
 obj-$(CONFIG_ROTTEN_IRQ)	+= old-irq.o
 obj-$(CONFIG_I8259)		+= i8259.o
 
 # transition from old time.c to new time.c
 # some boards uses old-time.c, some use time.c, and some use their own ones
-export-objs			+= old-time.o time.o
 obj-$(CONFIG_OLD_TIME_C)	+= old-time.o
 obj-$(CONFIG_NEW_TIME_C)	+= time.o
 
diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c
--- a/arch/mips/mm/init.c	Thu Aug  1 14:17:41 2002
+++ b/arch/mips/mm/init.c	Thu Aug  1 14:17:41 2002
@@ -24,7 +24,6 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
diff -Nru a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S
--- a/arch/mips64/kernel/scall_64.S	Thu Aug  1 14:17:36 2002
+++ b/arch/mips64/kernel/scall_64.S	Thu Aug  1 14:17:36 2002
@@ -333,8 +333,8 @@
 	PTR	sys_rt_sigtimedwait
 	PTR	sys_rt_sigqueueinfo
 	PTR	sys_rt_sigsuspend
-	PTR	sys_pread				/* 5200 */
-	PTR	sys_pwrite
+	PTR	sys_pread64				/* 5200 */
+	PTR	sys_pwrite64
 	PTR	sys_chown
 	PTR	sys_getcwd
 	PTR	sys_capget
diff -Nru a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c
--- a/arch/mips64/mm/init.c	Thu Aug  1 14:17:36 2002
+++ b/arch/mips64/mm/init.c	Thu Aug  1 14:17:36 2002
@@ -21,7 +21,6 @@
 #include <linux/bootmem.h>
 #include <linux/highmem.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
diff -Nru a/arch/ppc/8260_io/Config.in b/arch/ppc/8260_io/Config.in
--- a/arch/ppc/8260_io/Config.in	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/8260_io/Config.in	Thu Aug  1 14:17:36 2002
@@ -26,7 +26,7 @@
       choice 'Type of PHY'	\
 	"LXT970		CONFIG_FCC_LXT970	\
 	 LXT971		CONFIG_FCC_LXT971	\
-	 QS6612		CONFIG_FCC_QS6612"	CONFIG_FCC_LXT971
+	 QS6612		CONFIG_FCC_QS6612"	LXT971
       fi
   fi
 fi
diff -Nru a/arch/ppc/8xx_io/Makefile b/arch/ppc/8xx_io/Makefile
--- a/arch/ppc/8xx_io/Makefile	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/8xx_io/Makefile	Thu Aug  1 14:17:40 2002
@@ -11,6 +11,8 @@
 
 O_TARGET 		:= 8xx_io.o
 
+export-objs		:= fec.o
+
 obj-y			:= commproc.o uart.o
 
 obj-$(CONFIG_FEC_ENET)	+= fec.o
diff -Nru a/arch/ppc/boot/common/misc-common.c b/arch/ppc/boot/common/misc-common.c
--- a/arch/ppc/boot/common/misc-common.c	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/boot/common/misc-common.c	Thu Aug  1 14:17:40 2002
@@ -75,7 +75,7 @@
 void _vprintk(void(*putc)(const char), const char *fmt0, va_list ap);
 unsigned char *ISA_io = NULL;
 
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
 extern unsigned long com_port;
 
 extern int serial_tstc(unsigned long com_port);
@@ -96,7 +96,7 @@
 
 int tstc(void)
 {
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
 	if(keyb_present)
 		return (CRT_tstc() || serial_tstc(com_port));
 	else
@@ -109,10 +109,10 @@
 int getc(void)
 {
 	while (1) {
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
 		if (serial_tstc(com_port))
 			return (serial_getc(com_port));
-#endif /* CONFIG_SERIAL_CONSOLE */
+#endif /* serial console */
 		if (keyb_present)
 			if(CRT_tstc())
 				return (CRT_getc());
@@ -124,11 +124,11 @@
 {
 	int x,y;
 
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
 	serial_putc(com_port, c);
 	if ( c == '\n' )
 		serial_putc(com_port, '\r');
-#endif /* CONFIG_SERIAL_CONSOLE */
+#endif /* serial console */
 
 	x = orig_x;
 	y = orig_y;
@@ -171,10 +171,10 @@
 	y = orig_y;
 
 	while ( ( c = *s++ ) != '\0' ) {
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SERIAL_8250_CONSOLE)
 	        serial_putc(com_port, c);
 	        if ( c == '\n' ) serial_putc(com_port, '\r');
-#endif /* CONFIG_SERIAL_CONSOLE */
+#endif /* serial console */
 
 		if ( c == '\n' ) {
 			x = 0;
diff -Nru a/arch/ppc/boot/prep/Makefile b/arch/ppc/boot/prep/Makefile
--- a/arch/ppc/boot/prep/Makefile	Thu Aug  1 14:17:41 2002
+++ b/arch/ppc/boot/prep/Makefile	Thu Aug  1 14:17:41 2002
@@ -27,7 +27,7 @@
 OBJCOPY_ARGS			= -O elf32-powerpc
 LIBS 				= ../lib/zlib.a
 
-boot-$(CONFIG_SERIAL_CONSOLE)	+= ../common/ns16550.o
+boot-$($CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o
 boot-$(CONFIG_VGA_CONSOLE)	+= vreset.o kbd.o
 
 EXTRA_TARGETS			:= $(boot-y)
diff -Nru a/arch/ppc/boot/prep/misc.c b/arch/ppc/boot/prep/misc.c
--- a/arch/ppc/boot/prep/misc.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/boot/prep/misc.c	Thu Aug  1 14:17:36 2002
@@ -56,9 +56,9 @@
 char *zimage_start;
 int zimage_size;
 
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_8250_CONSOLE)
 unsigned long com_port;
-#endif /* CONFIG_SERIAL_CONSOLE */
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
 #ifdef CONFIG_VGA_CONSOLE
 char *vidmem = (char *)0xC00B8000;
 int lines = 25, cols = 80;
@@ -135,9 +135,9 @@
 	unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base;
 
 	serial_fixups();
-#if defined(CONFIG_SERIAL_CONSOLE)
+#if defined(CONFIG_SERIAL_8250_CONSOLE)
 	com_port = serial_init(0, NULL);
-#endif /* CONFIG_SERIAL_CONSOLE */
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
 #if defined(CONFIG_VGA_CONSOLE)
 	vga_init((unsigned char *)0xC0000000);
 #endif /* CONFIG_VGA_CONSOLE */
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/boot/simple/Makefile	Thu Aug  1 14:17:36 2002
@@ -136,9 +136,9 @@
 ifeq ($(CONFIG_SERIAL_CONSOLE),y)
 boot-$(CONFIG_8xx)		+= m8xx_tty.o
 boot-$(CONFIG_8260)		+= m8260_tty.o
-boot-$(CONFIG_GT64260_CONSOLE)   += gt64260_tty.o
-boot-$(CONFIG_SERIAL)		+= ../common/ns16550.o
+boot-$(CONFIG_GT64260_CONSOLE)	+= gt64260_tty.o
 endif
+boot-$(CONFIG_SERIAL_8250_CONSOLE) += ../common/ns16550.o
 
 EXTRA_TARGETS			:= $(boot-y)
 LIBS				:= ../lib/zlib.a
diff -Nru a/arch/ppc/boot/simple/misc-spruce.c b/arch/ppc/boot/simple/misc-spruce.c
--- a/arch/ppc/boot/simple/misc-spruce.c	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/boot/simple/misc-spruce.c	Thu Aug  1 14:17:40 2002
@@ -189,7 +189,7 @@
 	unsigned char header_type;
 	unsigned int bar0;
 
-#ifdef CONFIG_SERIAL_CONSOLE
+#ifdef CONFIG_SERIAL_8250_CONSOLE
 	/* Initialize the serial console port */
 	com_port = serial_init(0, NULL);
 #endif
diff -Nru a/arch/ppc/config.in b/arch/ppc/config.in
--- a/arch/ppc/config.in	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/config.in	Thu Aug  1 14:17:36 2002
@@ -365,6 +365,10 @@
    bool 'Support for RTAS (RunTime Abstraction Services) in /proc' CONFIG_PPC_RTAS
    bool 'Support for PReP Residual Data' CONFIG_PREP_RESIDUAL
    dep_bool '  Support for reading of PReP Residual Data in /proc' CONFIG_PROC_PREPRESIDUAL $CONFIG_PREP_RESIDUAL
+   define_bool CONFIG_PPCBUG_NVRAM y
+fi
+if [ "$CONFIG_PPLUS" = "y" -o "$CONFIG_LOPEC" = "y" ]; then
+   bool 'Enable reading PPCBUG NVRAM during boot' CONFIG_PPCBUG_NVRAM
 fi
 
 bool 'Default bootloader kernel arguments' CONFIG_CMDLINE_BOOL
diff -Nru a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
--- a/arch/ppc/kernel/Makefile	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/kernel/Makefile	Thu Aug  1 14:17:40 2002
@@ -35,6 +35,7 @@
 ifneq ($(CONFIG_PPC_ISERIES),y)
 obj-$(CONFIG_PCI)		+= pci-dma.o
 endif
+obj-$(CONFIG_PPCBUG_NVRAM)	+= prep_nvram.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_TAU)		+= temp.o
diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c
--- a/arch/ppc/kernel/irq.c	Thu Aug  1 14:17:39 2002
+++ b/arch/ppc/kernel/irq.c	Thu Aug  1 14:17:39 2002
@@ -178,15 +178,6 @@
 	return 0;
 }
 
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
-/* Name change so we can catch standard drivers that potentially mess up
- * the internal interrupt controller on 8xx and 8260.  Just bear with me,
- * I don't like this either and I am searching a better solution.  For
- * now, this is what I need. -- Dan
- */
-#define request_irq	request_8xxirq
-#endif
-
 void free_irq(unsigned int irq, void* dev_id)
 {
 	irq_desc_t *desc;
@@ -212,11 +203,7 @@
 			}
 			spin_unlock_irqrestore(&desc->lock,flags);
 
-#ifdef CONFIG_SMP
-			/* Wait to make sure it's not being used on another CPU */
-			while (desc->status & IRQ_INPROGRESS)
-				barrier();
-#endif
+			synchronize_irq(irq);
 			irq_kfree(action);
 			return;
 		}
@@ -289,8 +276,8 @@
  *
  *	This function may be called from IRQ context.
  */
- 
- void disable_irq_nosync(unsigned int irq)
+
+void disable_irq_nosync(unsigned int irq)
 {
 	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
@@ -320,12 +307,7 @@
 void disable_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-
-	if (!local_irq_count(smp_processor_id())) {
-		do {
-			barrier();
-		} while (irq_desc[irq].status & IRQ_INPROGRESS);
-	}
+	synchronize_irq(irq);
 }
 
 /**
@@ -525,11 +507,10 @@
 }
 
 #ifndef CONFIG_PPC_ISERIES	/* iSeries version is in iSeries_pic.c */
-int do_IRQ(struct pt_regs *regs)
+void do_IRQ(struct pt_regs *regs)
 {
-	int cpu = smp_processor_id();
 	int irq, first = 1;
-        hardirq_enter( cpu );
+        irq_enter();
 
 	/*
 	 * Every platform is required to implement ppc_md.get_irq.
@@ -546,11 +527,7 @@
 	if (irq != -2 && first)
 		/* That's not SMP safe ... but who cares ? */
 		ppc_spurious_interrupts++;
-        hardirq_exit( cpu );
-
-	if (softirq_pending(cpu))
-		do_softirq();
-	return 1; /* lets ret_from_int know we can do checks */
+        irq_exit();
 }
 #endif /* CONFIG_PPC_ISERIES */
 
@@ -582,262 +559,14 @@
 }
 
 #ifdef CONFIG_SMP
-unsigned char global_irq_holder = NO_PROC_ID;
-unsigned volatile long global_irq_lock; /* pendantic :long for set_bit--RR*/
-
-atomic_t global_bh_count;
-
-static void show(char * str)
+void synchronize_irq(unsigned int irq)
 {
-	int cpu = smp_processor_id();
-
-	printk("\n%s, CPU %d:\n", str, cpu);
-	printk("irq:  [%d %d]\n",
-	       local_irq_count(0),
-	       local_irq_count(1));
-	printk("bh:   %d [%d %d]\n",
-	       atomic_read(&global_bh_count),
-	       local_bh_count(0),
-	       local_bh_count(1));
-}
-
-static inline void wait_on_bh(void)
-{
-	int count = MAXCOUNT;
-	do {
-		if (!--count) {
-			show("wait_on_bh");
-			count = ~0;
-		}
-		/* nothing .. wait for the other bh's to go away */
-	} while (atomic_read(&global_bh_count) != 0);
-}
-
-
-static inline void wait_on_irq(int cpu)
-{
-	int count = MAXCOUNT;
-
-	for (;;) {
-
-		/*
-		 * Wait until all interrupts are gone. Wait
-		 * for bottom half handlers unless we're
-		 * already executing in one..
-		 */
-		if (!irqs_running())
-			if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock))
-					break;
-
-		/* Duh, we have to loop. Release the lock to avoid deadlocks */
-		clear_bit(0,&global_irq_lock);
-
-		for (;;) {
-			if (!--count) {
-				show("wait_on_irq");
-				count = ~0;
-			}
-			local_irq_enable();
-			/* 
-			 * We have to allow irqs to arrive between local_irq_enable and local_irq_disable
-			 * Some cpus apparently won't cause the interrupt
-			 * for several instructions. We hope that isync will
-			 * catch this --Troy
-			 */
-			__asm__ __volatile__ ("isync");
-			local_irq_disable();
-			if (irqs_running())
-				continue;
-			if (global_irq_lock)
-				continue;
-			if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock))
-				continue;
-			if (!test_and_set_bit(0,&global_irq_lock))
-				break;
-		}
-	}
-}
-
-/*
- * This is called when we want to synchronize with
- * bottom half handlers. We need to wait until
- * no other CPU is executing any bottom half handler.
- *
- * Don't wait if we're already running in an interrupt
- * context or are inside a bh handler.
- */
-void synchronize_bh(void)
-{
-	if (atomic_read(&global_bh_count) && !in_interrupt())
-		wait_on_bh();
-}
-
-/*
- * This is called when we want to synchronize with
- * interrupts. We may for example tell a device to
- * stop sending interrupts: but to make sure there
- * are no interrupts that are executing on another
- * CPU we need to call this function.
- */
-void synchronize_irq(void)
-{
-	if (irqs_running()) {
-		/* Stupid approach */
-		cli();
-		sti();
-	}
-}
-
-static inline void get_irqlock(int cpu)
-{
-	unsigned int loops = MAXCOUNT;
-
-	if (test_and_set_bit(0,&global_irq_lock)) {
-		/* do we already hold the lock? */
-		if ((unsigned char) cpu == global_irq_holder)
-			return;
-		/* Uhhuh.. Somebody else got it. Wait.. */
-		do {
-			do {
-				if (loops-- == 0) {
-					printk("get_irqlock(%d) waiting, global_irq_holder=%d\n", cpu, global_irq_holder);
-#ifdef CONFIG_XMON
-					xmon(0);
-#endif
-				}
-			} while (test_bit(0,&global_irq_lock));
-		} while (test_and_set_bit(0,&global_irq_lock));		
-	}
-	/* 
-	 * We also need to make sure that nobody else is running
-	 * in an interrupt context. 
-	 */
-	wait_on_irq(cpu);
-
-	/*
-	 * Ok, finally..
-	 */
-	global_irq_holder = cpu;
-}
-
-/*
- * A global "cli()" while in an interrupt context
- * turns into just a local cli(). Interrupts
- * should use spinlocks for the (very unlikely)
- * case that they ever want to protect against
- * each other.
- *
- * If we already have local interrupts disabled,
- * this will not turn a local disable into a
- * global one (problems with spinlocks: this makes
- * save_flags+cli+sti usable inside a spinlock).
- */
-void __global_cli(void)
-{
-	unsigned long flags;
-	
-	local_save_flags(flags);
-	if (flags & (1 << 15)) {
-		int cpu = smp_processor_id();
-		local_irq_disable();
-		if (!local_irq_count(cpu))
-			get_irqlock(cpu);
-	}
-}
-
-void __global_sti(void)
-{
-	int cpu = smp_processor_id();
-
-	if (!local_irq_count(cpu))
-		release_irqlock(cpu);
-	local_irq_enable();
-}
-
-/*
- * SMP flags value to restore to:
- * 0 - global cli
- * 1 - global sti
- * 2 - local cli
- * 3 - local sti
- */
-unsigned long __global_save_flags(void)
-{
-	int retval;
-	int local_enabled;
-	unsigned long flags;
-
-	local_save_flags(flags);
-	local_enabled = (flags >> 15) & 1;
-	/* default to local */
-	retval = 2 + local_enabled;
-
-	/* check for global flags if we're not in an interrupt */
-	if (!local_irq_count(smp_processor_id())) {
-		if (local_enabled)
-			retval = 1;
-		if (global_irq_holder == (unsigned char) smp_processor_id())
-			retval = 0;
-	}
-	return retval;
-}
-
-int
-tb(long vals[],
-   int  max_size)
-{
-   register unsigned long *orig_sp __asm__ ("r1");
-   register unsigned long lr __asm__ ("r3");
-   unsigned long *sp;
-   int i;
-
-   asm volatile ("mflr 3");
-   vals[0] = lr;
-   sp = (unsigned long *) *orig_sp;
-   sp = (unsigned long *) *sp;
-   for (i=1; i<max_size; i++) {
-      if (sp == 0) {
-         break;
-      }
-
-      vals[i] = *(sp+1);
-      sp = (unsigned long *) *sp;
-   }
-
-   return i;
-}
+        /* is there anything to synchronize with? */
+	if (!irq_desc[irq].action)
+		return;
 
-void __global_restore_flags(unsigned long flags)
-{
-	switch (flags) {
-	case 0:
-		__global_cli();
-		break;
-	case 1:
-		__global_sti();
-		break;
-	case 2:
-		local_irq_disable();
-		break;
-	case 3:
-		local_irq_enable();
-		break;
-	default:
-	{
-		unsigned long trace[5];
-                int           count;
-                int           i;
-
-		printk("global_restore_flags: %08lx (%08lx)\n",
-			flags, (&flags)[-1]);
-                count = tb(trace, 5);
-                printk("tb:");
-                for(i=0; i<count; i++) {
-			printk(" %8.8lx", trace[i]);
-		}
-		printk("\n");
-	}
-	}
+	while (irq_desc[irq].status & IRQ_INPROGRESS)
+		barrier();
 }
 #endif /* CONFIG_SMP */
 
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/kernel/misc.S	Thu Aug  1 14:17:40 2002
@@ -1251,8 +1251,8 @@
 	.long sys_rt_sigtimedwait
 	.long sys_rt_sigqueueinfo
 	.long ppc_rt_sigsuspend
-	.long sys_pread
-	.long sys_pwrite	/* 180 */
+	.long sys_pread64
+	.long sys_pwrite64	/* 180 */
 	.long sys_chown
 	.long sys_getcwd
 	.long sys_capget
diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/kernel/ppc_htab.c	Thu Aug  1 14:17:36 2002
@@ -381,47 +381,6 @@
 		}
 	}	
 	
-
-	return count;
-	
-#if 0 /* resizing htab is a bit difficult right now -- Cort */
-	unsigned long size;
-	extern void reset_SDR1(void);
-	
-	/* only know how to set size right now */
-	if ( strncmp( buffer, "size ", 5) )
-		return -EINVAL;
-
-	size = simple_strtoul( &buffer[5], NULL, 10 );
-	
-	/* only allow to shrink */
-	if ( size >= Hash_size>>10 )
-		return -EINVAL;
-
-	/* minimum size of htab */
-	if ( size < 64 )
-		return -EINVAL;
-	
-	/* make sure it's a multiple of 64k */
-	if ( size % 64 )
-		return -EINVAL;
-	
-	printk("Hash table resize to %luk\n", size);
-	/*
-	 * We need to rehash all kernel entries for the new htab size.
-	 * Kernel only since we do a flush_tlb_all().  Since it's kernel
-	 * we only need to bother with vsids 0-15.  To avoid problems of
-	 * clobbering un-rehashed values we put the htab at a new spot
-	 * and put everything there.
-	 * -- Cort
-	 */
-	Hash_size = size<<10;
-	Hash_mask = (Hash_size >> 6) - 1;
-        _SDR1 = __pa(Hash) | (Hash_mask >> 10);
-	flush_tlb_all();
-
-	reset_SDR1();
-#endif	
 	return count;
 #else /* CONFIG_PPC_STD_MMU */
 	return 0;
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	Thu Aug  1 14:17:41 2002
+++ b/arch/ppc/kernel/ppc_ksyms.c	Thu Aug  1 14:17:41 2002
@@ -207,12 +207,6 @@
 EXPORT_SYMBOL(giveup_altivec);
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(global_irq_lock);
-EXPORT_SYMBOL(global_irq_holder);
-EXPORT_SYMBOL(__global_cli);
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
 #ifdef CONFIG_DEBUG_SPINLOCK
 EXPORT_SYMBOL(_raw_spin_lock);
 EXPORT_SYMBOL(_raw_spin_unlock);
diff -Nru a/arch/ppc/kernel/prep_nvram.c b/arch/ppc/kernel/prep_nvram.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ppc/kernel/prep_nvram.c	Thu Aug  1 14:17:40 2002
@@ -0,0 +1,148 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * arch/ppc/kernel/prep_nvram.c
+ *
+ * Copyright (C) 1998  Corey Minyard
+ *
+ * This reads the NvRAM on PReP compliant machines (generally from IBM or
+ * Motorola).  Motorola kept the format of NvRAM in their ROM, PPCBUG, the
+ * same, long after they had stopped producing PReP compliant machines.  So
+ * this code is useful in those cases as well.
+ *
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+#include <asm/sections.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+
+static char nvramData[MAX_PREP_NVRAM];
+static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
+
+unsigned char __prep prep_nvram_read_val(int addr)
+{
+	outb(addr, PREP_NVRAM_AS0);
+	outb(addr>>8, PREP_NVRAM_AS1);
+	return inb(PREP_NVRAM_DATA);
+}
+  
+void __prep prep_nvram_write_val(int           addr,
+			  unsigned char val)
+{
+	outb(addr, PREP_NVRAM_AS0);
+	outb(addr>>8, PREP_NVRAM_AS1);
+   	outb(val, PREP_NVRAM_DATA);
+}
+  
+void __init init_prep_nvram(void)
+{
+	unsigned char *nvp;
+	int  i;
+	int  nvramSize;
+
+	/*
+	 * The following could fail if the NvRAM were corrupt but
+	 * we expect the boot firmware to have checked its checksum
+	 * before boot
+	 */
+	nvp = (char *) &nvram->Header;
+	for (i=0; i<sizeof(HEADER); i++)
+	{
+		*nvp = ppc_md.nvram_read_val(i);
+		nvp++;
+	}
+	
+	/*
+	 * The PReP NvRAM may be any size so read in the header to
+	 * determine how much we must read in order to get the complete
+	 * GE area
+	 */
+	nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
+	if(nvramSize>MAX_PREP_NVRAM)
+	{
+		/*
+		 * NvRAM is too large
+		 */
+		nvram->Header.GELength=0;
+		return;
+	}
+
+	/*
+	 * Read the remainder of the PReP NvRAM
+	 */
+	nvp = (char *) &nvram->GEArea[0];
+	for (i=sizeof(HEADER); i<nvramSize; i++)
+	{
+		*nvp = ppc_md.nvram_read_val(i);
+		nvp++;
+	}
+}
+
+__prep
+char __prep *prep_nvram_get_var(const char *name)
+{
+	char *cp;
+	int  namelen;
+
+	namelen = strlen(name);
+	cp = prep_nvram_first_var();
+	while (cp != NULL) {
+		if ((strncmp(name, cp, namelen) == 0)
+		    && (cp[namelen] == '='))
+		{
+			return cp+namelen+1;
+		}
+		cp = prep_nvram_next_var(cp);
+	}
+
+	return NULL;
+}
+
+__prep
+char __prep *prep_nvram_first_var(void)
+{
+        if (nvram->Header.GELength == 0) {
+		return NULL;
+	} else {
+		return (((char *)nvram)
+			+ ((unsigned int) nvram->Header.GEAddress));
+	}
+}
+
+__prep
+char __prep *prep_nvram_next_var(char *name)
+{
+	char *cp;
+
+
+	cp = name;
+	while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+	       && (*cp != '\0'))
+	{
+		cp++;
+	}
+
+	/* Skip over any null characters. */
+	while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
+	       && (*cp == '\0'))
+	{
+		cp++;
+	}
+
+	if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
+		return cp;
+	} else {
+		return NULL;
+	}
+}
+
+
+
diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c
--- a/arch/ppc/kernel/process.c	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/kernel/process.c	Thu Aug  1 14:17:40 2002
@@ -202,8 +202,7 @@
 	struct thread_struct *new_thread, *old_thread;
 	unsigned long s;
 	
-	local_save_flags(s);
-	local_irq_disable();
+	local_irq_save(s);
 #if CHECK_STACK
 	check_stack(prev);
 	check_stack(new);
diff -Nru a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
--- a/arch/ppc/kernel/temp.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/kernel/temp.c	Thu Aug  1 14:17:36 2002
@@ -124,27 +124,27 @@
 
 void TAUException(struct pt_regs * regs)
 {
-	unsigned long cpu = smp_processor_id();
+	int cpu = smp_processor_id();
 
-	hardirq_enter(cpu);
+	irq_enter();
 	tau[cpu].interrupts++;
 	
 	TAUupdate(cpu);
 
-	hardirq_exit(cpu);
-	return;
+	irq_exit();
 }
 #endif /* CONFIG_TAU_INT */
 
 static void tau_timeout(void * info)
 {
-	unsigned long cpu = smp_processor_id();
+	int cpu;
 	unsigned long flags;
 	int size;
 	int shrink;
  
 	/* disabling interrupts *should* be okay */
-	save_flags(flags); cli();
+	local_irq_save(flags);
+	cpu = smp_processor_id();
 
 #ifndef CONFIG_TAU_INT
 	TAUupdate(cpu);
@@ -186,7 +186,7 @@
 	 */
 	mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E);
 
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static void tau_timeout_smp(unsigned long unused)
diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c
--- a/arch/ppc/kernel/time.c	Thu Aug  1 14:17:37 2002
+++ b/arch/ppc/kernel/time.c	Thu Aug  1 14:17:37 2002
@@ -75,7 +75,7 @@
 
 unsigned long disarm_decr[NR_CPUS];
 
-extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+extern struct timezone sys_tz;
 
 /* keep track of when we need to update the rtc */
 time_t last_rtc_update;
@@ -151,7 +151,7 @@
  * with interrupts disabled.
  * We set it up to overflow again in 1/HZ seconds.
  */
-int timer_interrupt(struct pt_regs * regs)
+void timer_interrupt(struct pt_regs * regs)
 {
 	int next_dec;
 	unsigned long cpu = smp_processor_id();
@@ -161,7 +161,7 @@
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
 
-	hardirq_enter(cpu);
+	irq_enter();
 	
 	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
@@ -214,12 +214,7 @@
 	if (ppc_md.heartbeat && !ppc_md.heartbeat_count--)
 		ppc_md.heartbeat();
 
-	hardirq_exit(cpu);
-
-	if (softirq_pending(cpu))
-		do_softirq();
-
-	return 1; /* lets ret_from_int know we can do checks */
+	irq_exit();
 }
 #endif /* CONFIG_PPC_ISERIES */
 
@@ -358,14 +353,11 @@
 	/* Not exact, but the timer interrupt takes care of this */
 	set_dec(tb_ticks_per_jiffy);
 
-	/* If platform provided a timezone (pmac), we correct the time
-	 * using do_sys_settimeofday() which in turn calls warp_clock()
-	 */
+	/* If platform provided a timezone (pmac), we correct the time */
         if (time_offset) {
-        	struct timezone tz;
-        	tz.tz_minuteswest = -time_offset / 60;
-        	tz.tz_dsttime = 0;
-        	do_sys_settimeofday(NULL, &tz);
+		sys_tz.tz_minuteswest = -time_offset / 60;
+		sys_tz.tz_dsttime = 0;
+		xtime.tv_sec -= time_offset;
         }
 }
 
@@ -373,6 +365,11 @@
 #define	STARTOFTIME		1970
 #define SECDAY			86400L
 #define SECYR			(SECDAY * 365)
+
+/*
+ * Note: this is wrong for 2100, but our signed 32-bit time_t will
+ * have overflowed long before that, so who cares.  -- paulus
+ */
 #define	leapyear(year)		((year) % 4 == 0)
 #define	days_in_year(a) 	(leapyear(a) ? 366 : 365)
 #define	days_in_month(a) 	(month_days[(a) - 1])
diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c
--- a/arch/ppc/mm/fault.c	Thu Aug  1 14:17:39 2002
+++ b/arch/ppc/mm/fault.c	Thu Aug  1 14:17:39 2002
@@ -189,16 +189,18 @@
 	 */
  survive:
         switch (handle_mm_fault(mm, vma, address, is_write)) {
-        case 1:
+        case VM_FAULT_MINOR:
                 current->min_flt++;
                 break;
-        case 2:
+        case VM_FAULT_MAJOR:
                 current->maj_flt++;
                 break;
-        case 0:
+        case VM_FAULT_SIGBUS:
                 goto do_sigbus;
-        default:
+        case VM_FAULT_OOM:
                 goto out_of_memory;
+	default:
+		BUG();
 	}
 
 	up_read(&mm->mmap_sem);
diff -Nru a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
--- a/arch/ppc/mm/mmu_decl.h	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/mm/mmu_decl.h	Thu Aug  1 14:17:40 2002
@@ -25,7 +25,6 @@
 #include <asm/tlbflush.h>
 
 extern void mapin_ram(void);
-extern void bat_mapin_ram(void);
 extern int map_page(unsigned long va, unsigned long pa, int flags);
 extern void setbat(int index, unsigned long virt, unsigned long phys,
 		   unsigned int size, int flags);
@@ -49,14 +48,17 @@
 #if defined(CONFIG_8xx)
 #define flush_HPTE(X, va, pg)	_tlbie(va)
 #define MMU_init_hw()		do { } while(0)
+#define mmu_mapin_ram()		(0UL)
 
 #elif defined(CONFIG_4xx)
 #define flush_HPTE(X, va, pg)	_tlbie(va)
 extern void MMU_init_hw(void);
+#define mmu_mapin_ram()		(0UL)
 
 #else
 /* anything except 4xx or 8xx */
 extern void MMU_init_hw(void);
+extern unsigned long mmu_mapin_ram(void);
 
 /* Be careful....this needs to be updated if we ever encounter 603 SMPs,
  * which includes all new 82xx processors.  We need tlbie/tlbsync here
diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
--- a/arch/ppc/mm/pgtable.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/mm/pgtable.c	Thu Aug  1 14:17:36 2002
@@ -252,31 +252,14 @@
 {
 	unsigned long v, p, s, f;
 
-#ifdef HAVE_BATS
-	if (!__map_without_bats)
-		bat_mapin_ram();
-#endif /* HAVE_BATS */
-
-	v = KERNELBASE;
-	p = PPC_MEMSTART;
-	for (s = 0; s < total_lowmem; s += PAGE_SIZE) {
-		/* On the MPC8xx, we want the page shared so we
-		 * don't get ASID compares on kernel space.
-		 */
-		f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED | _PAGE_HWEXEC;
-#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
-		/* Allows stub to set breakpoints everywhere */
-		f |= _PAGE_WRENABLE;
-#else	/* !CONFIG_KGDB && !CONFIG_XMON */
-		if ((char *) v < _stext || (char *) v >= etext)
-			f |= _PAGE_WRENABLE;
-#ifdef CONFIG_PPC_STD_MMU
+	s = mmu_mapin_ram();
+	v = KERNELBASE + s;
+	p = PPC_MEMSTART + s;
+	for (; s < total_lowmem; s += PAGE_SIZE) {
+		if ((char *) v >= _stext && (char *) v < etext)
+			f = _PAGE_RAM_TEXT;
 		else
-			/* On the powerpc (not all), no user access
-			   forces R/W kernel access */
-			f |= _PAGE_USER;
-#endif /* CONFIG_PPC_STD_MMU */
-#endif /* CONFIG_KGDB || CONFIG_XMON */
+			f = _PAGE_RAM;
 		map_page(v, p, f);
 		v += PAGE_SIZE;
 		p += PAGE_SIZE;
diff -Nru a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
--- a/arch/ppc/mm/ppc_mmu.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/mm/ppc_mmu.c	Thu Aug  1 14:17:36 2002
@@ -87,12 +87,15 @@
 	return 0;
 }
 
-void __init bat_mapin_ram(void)
+unsigned long __init mmu_mapin_ram(void)
 {
 	unsigned long tot, bl, done;
 	unsigned long max_size = (256<<20);
 	unsigned long align;
 
+	if (__map_without_bats)
+		return 0;
+
 	/* Set up BAT2 and if necessary BAT3 to cover RAM. */
 
 	/* Make sure we don't map a block larger than the
@@ -119,7 +122,10 @@
 				break;
 		setbat(3, KERNELBASE+done, PPC_MEMSTART+done, bl,
 		       _PAGE_KERNEL);
+		done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
 	}
+
+	return done;
 }
 
 /*
diff -Nru a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
--- a/arch/ppc/mm/tlb.c	Thu Aug  1 14:17:41 2002
+++ b/arch/ppc/mm/tlb.c	Thu Aug  1 14:17:41 2002
@@ -31,13 +31,42 @@
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/highmem.h>
+#include <asm/tlbflush.h>
+#include <asm/tlb.h>
 
 #include "mmu_decl.h"
 
 /*
+ * Called when unmapping pages to flush entries from the TLB/hash table.
+ */
+void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr)
+{
+	unsigned long ptephys;
+
+	if (Hash != 0) {
+		ptephys = __pa(ptep) & PAGE_MASK;
+		flush_hash_pages(mm->context, addr, ptephys, 1);
+	}
+}
+
+/*
+ * Called at the end of a mmu_gather operation to make sure the
+ * TLB flush is completely done.
+ */
+void tlb_flush(mmu_gather_t *tlb)
+{
+	if (Hash == 0) {
+		/*
+		 * 603 needs to flush the whole TLB here since
+		 * it doesn't use a hash table.
+		 */
+		_tlbia();
+	}
+}
+
+/*
  * TLB flushing:
  *
- *  - flush_tlb_all() flushes all processes TLBs
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  *  - flush_tlb_page(vma, vmaddr) flushes one page
  *  - flush_tlb_range(vma, start, end) flushes a range of pages
@@ -92,29 +121,6 @@
 }
 
 /*
- * Flush all tlb/hash table entries (except perhaps for those
- * mapping RAM starting at PAGE_OFFSET, since they never change).
- */
-void
-flush_tlb_all(void)
-{
-	/*
-	 * Just flush the kernel part of the address space, that's
-	 * all that the current callers of this require.
-	 * Eventually I hope to persuade the powers that be that
-	 * we can and should dispense with flush_tlb_all().
-	 *  -- paulus.
-	 *
-	 * In fact this should never get called now that we
-	 * have flush_tlb_kernel_range.  -- paulus
-	 */
-	printk(KERN_ERR "flush_tlb_all called from %p\n",
-	       __builtin_return_address(0));
-	flush_range(&init_mm, TASK_SIZE, ~0UL);
-	FINISH_FLUSH;
-}
-
-/*
  * Flush kernel TLB entries in the given range
  */
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -124,24 +130,19 @@
 }
 
 /*
- * Flush all the (user) entries for the address space described
- * by mm.  We can't rely on mm->mmap describing all the entries
- * that might be in the hash table.
+ * Flush all the (user) entries for the address space described by mm.
  */
 void flush_tlb_mm(struct mm_struct *mm)
 {
+	struct vm_area_struct *mp;
+
 	if (Hash == 0) {
 		_tlbia();
 		return;
 	}
 
-	if (mm->map_count) {
-		struct vm_area_struct *mp;
-		for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
-			flush_range(mp->vm_mm, mp->vm_start, mp->vm_end);
-	} else {
-		flush_range(mm, 0, TASK_SIZE);
-	}
+	for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
+		flush_range(mp->vm_mm, mp->vm_start, mp->vm_end);
 	FINISH_FLUSH;
 }
 
@@ -160,7 +161,6 @@
 		flush_hash_pages(mm->context, vmaddr, pmd_val(*pmd), 1);
 	FINISH_FLUSH;
 }
-
 
 /*
  * For each address in the range, find the pte for the address
diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
--- a/arch/ppc/platforms/Makefile	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/platforms/Makefile	Thu Aug  1 14:17:40 2002
@@ -32,7 +32,7 @@
 obj-$(CONFIG_ALL_PPC)		+= pmac_pic.o pmac_setup.o pmac_time.o \
 					pmac_feature.o pmac_pci.o chrp_setup.o\
 					chrp_time.o chrp_pci.o prep_pci.o \
-					prep_time.o prep_nvram.o prep_setup.o
+					prep_time.o prep_setup.o
 ifeq ($(CONFIG_ALL_PPC),y)
 obj-$(CONFIG_NVRAM)		+= pmac_nvram.o
 endif
@@ -50,7 +50,7 @@
 obj-$(CONFIG_MVME5100)		+= mvme5100_setup.o mvme5100_pci.o
 obj-$(CONFIG_PCORE)		+= pcore_setup.o pcore_pci.o
 obj-$(CONFIG_POWERPMC250)	+= powerpmc250.o
-obj-$(CONFIG_PPLUS)		+= pplus_pci.o pplus_setup.o prep_nvram.o
+obj-$(CONFIG_PPLUS)		+= pplus_pci.o pplus_setup.o
 obj-$(CONFIG_PRPMC750)		+= prpmc750_setup.o prpmc750_pci.o
 obj-$(CONFIG_PRPMC800)		+= prpmc800_setup.o prpmc800_pci.o
 obj-$(CONFIG_SANDPOINT)		+= sandpoint_setup.o sandpoint_pci.o
diff -Nru a/arch/ppc/platforms/cpc700.h b/arch/ppc/platforms/cpc700.h
--- a/arch/ppc/platforms/cpc700.h	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/platforms/cpc700.h	Thu Aug  1 14:17:40 2002
@@ -6,7 +6,7 @@
  * Author: Mark A. Greer
  *         mgreer@mvista.com
  *
- * Copyright 2000 MontaVista Software Inc.
+ * Copyright 2000-2002 MontaVista Software Inc.
  *
  * 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
@@ -101,7 +101,7 @@
  * UIC Exports...
  */
 extern struct hw_interrupt_type cpc700_pic;
-extern unsigned int cpc700_irq_assigns[27][2];
+extern unsigned int cpc700_irq_assigns[32][2];
  
 extern void __init cpc700_init_IRQ(void);
 extern int cpc700_get_irq(struct pt_regs *);
diff -Nru a/arch/ppc/platforms/cpc700_pic.c b/arch/ppc/platforms/cpc700_pic.c
--- a/arch/ppc/platforms/cpc700_pic.c	Thu Aug  1 14:17:37 2002
+++ b/arch/ppc/platforms/cpc700_pic.c	Thu Aug  1 14:17:37 2002
@@ -8,7 +8,7 @@
  *          mporter@mvista.com
  *          jpeters@mvista.com
  *
- * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2001-2002 MontaVista Software Inc.
  *
  * 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
@@ -168,7 +168,7 @@
 		cpc700_pic_init_irq(i);
 	}
 
-	for (i = 20; i < 27; i++) {
+	for (i = 20; i < 32; i++) {
 		irq_desc[i].handler = &cpc700_pic;
 		cpc700_pic_init_irq(i);
 	}
diff -Nru a/arch/ppc/platforms/iSeries_pic.c b/arch/ppc/platforms/iSeries_pic.c
--- a/arch/ppc/platforms/iSeries_pic.c	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/platforms/iSeries_pic.c	Thu Aug  1 14:17:40 2002
@@ -42,7 +42,7 @@
 extern void iSeries_smp_message_recv( struct pt_regs * );
 unsigned lpEvent_count = 0;
 
-int do_IRQ(struct pt_regs *regs)
+void do_IRQ(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 	unsigned long flags;
@@ -52,7 +52,7 @@
 	if ( is_soft_enabled() )
 		BUG();
 	
-        hardirq_enter( cpu );
+	irq_enter();
 
 	paca = (struct Paca *)mfspr(SPRG1);
 
@@ -65,21 +65,16 @@
 
 	lpq = paca->lpQueuePtr;
 	if ( lpq ) {
-		local_save_flags( flags );
-		local_irq_disable();
+		local_irq_save(flags);
 		lpEvent_count += ItLpQueue_process( lpq, regs );
 		local_irq_restore( flags );
 	}
 
-        hardirq_exit( cpu );
+	irq_exit();
 
 	if ( paca->xLpPacaPtr->xDecrInt ) {
 		paca->xLpPacaPtr->xDecrInt = 0;
 		/* Signal a fake decrementer interrupt */
 		timer_interrupt( regs );
 	}
-
-	if (softirq_pending(cpu))
-		do_softirq();
-	return 1; /* lets ret_from_int know we can do checks */
 }
diff -Nru a/arch/ppc/platforms/iSeries_time.c b/arch/ppc/platforms/iSeries_time.c
--- a/arch/ppc/platforms/iSeries_time.c	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc/platforms/iSeries_time.c	Thu Aug  1 14:17:40 2002
@@ -102,7 +102,7 @@
 int timerRetDisabled = 0;
 
 extern unsigned long iSeries_dec_value;
-int timer_interrupt(struct pt_regs * regs)
+void timer_interrupt(struct pt_regs * regs)
 {
 	long next_dec;
 	struct Paca * paca;
@@ -117,7 +117,7 @@
 	else
 	  timerRetDisabled++;
 	
-	hardirq_enter(cpu);
+	irq_enter();
 
 	if (!user_mode(regs))
 		ppc_do_profile(instruction_pointer(regs));
@@ -149,9 +149,5 @@
 	paca->xLpPacaPtr->xDecrInt = 0;
 	set_dec( (unsigned)next_dec );
 
-	hardirq_exit(cpu);
-
-	if (softirq_pending(cpu))
-		do_softirq();
-	return 1;
+	irq_exit();
 }
diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c
--- a/arch/ppc/platforms/lopec_setup.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/platforms/lopec_setup.c	Thu Aug  1 14:17:36 2002
@@ -33,7 +33,9 @@
 #include <asm/bootinfo.h>
 #include <asm/mpc10x.h>
 #include <asm/hw_irq.h>
+#include <asm/prep_nvram.h>
 
+extern char saved_command_line[];
 extern void lopec_find_bridges(void);
 
 /*
@@ -332,6 +334,21 @@
 
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
+#endif
+#ifdef CONFIG_PPCBUG_NVRAM
+	/* Read in NVRAM data */ 
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if ( cmd_line[0] == '\0' ) {
+		char *bootargs;
+		 bootargs = prep_nvram_get_var("bootargs");
+		 if (bootargs != NULL) {
+			 strcpy(cmd_line, bootargs);
+			 /* again.. */
+			 strcpy(saved_command_line, cmd_line);
+		}
+	}
 #endif
 }
 
diff -Nru a/arch/ppc/platforms/pplus_setup.c b/arch/ppc/platforms/pplus_setup.c
--- a/arch/ppc/platforms/pplus_setup.c	Thu Aug  1 14:17:41 2002
+++ b/arch/ppc/platforms/pplus_setup.c	Thu Aug  1 14:17:41 2002
@@ -9,7 +9,7 @@
  * Cort Dougan, Johnnie Peters, Matt Porter, and
  * Troy Benjegerdes.
  *
- * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2001-2002 MontaVista Software Inc.
  *
  * 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
@@ -76,8 +76,9 @@
 
 TODC_ALLOC();
 
-extern void pplus_setup_hose(void);
+extern char saved_command_line[];
 
+extern void pplus_setup_hose(void);
 extern void pplus_set_VIA_IDE_native(void);
 
 extern unsigned long loops_per_jiffy;
@@ -131,7 +132,8 @@
 		ROOT_DEV = Root_SDA2;
 #endif
 
-	printk("PowerPlus port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n");
+	printk(KERN_INFO "Motorola PowerPlus Platform\n");
+	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
 
 	if ( ppc_md.progress )
 		ppc_md.progress("pplus_setup_arch: raven_init\n", 0);
@@ -144,6 +146,21 @@
 	conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
+#endif
+#ifdef CONFIG_PPCBUG_NVRAM
+	/* Read in NVRAM data */ 
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if ( cmd_line[0] == '\0' ) {
+		char *bootargs;
+		 bootargs = prep_nvram_get_var("bootargs");
+		 if (bootargs != NULL) {
+			 strcpy(cmd_line, bootargs);
+			 /* again.. */
+			 strcpy(saved_command_line, cmd_line);
+		}
+	}
 #endif
 	if ( ppc_md.progress )
 		ppc_md.progress("pplus_setup_arch: exit\n", 0);
diff -Nru a/arch/ppc/platforms/prep_nvram.c b/arch/ppc/platforms/prep_nvram.c
--- a/arch/ppc/platforms/prep_nvram.c	Thu Aug  1 14:17:40 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,143 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- *  arch/ppc/platforms/prep_nvram.c
- *
- *  Copyright (C) 1998  Corey Minyard
- *
- */
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-
-#include <asm/sections.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/machdep.h>
-#include <asm/prep_nvram.h>
-
-static char nvramData[MAX_PREP_NVRAM];
-static NVRAM_MAP *nvram=(NVRAM_MAP *)&nvramData[0];
-
-unsigned char __prep prep_nvram_read_val(int addr)
-{
-	outb(addr, PREP_NVRAM_AS0);
-	outb(addr>>8, PREP_NVRAM_AS1);
-	return inb(PREP_NVRAM_DATA);
-}
-  
-void __prep prep_nvram_write_val(int           addr,
-			  unsigned char val)
-{
-	outb(addr, PREP_NVRAM_AS0);
-	outb(addr>>8, PREP_NVRAM_AS1);
-   	outb(val, PREP_NVRAM_DATA);
-}
-  
-void __init init_prep_nvram(void)
-{
-	unsigned char *nvp;
-	int  i;
-	int  nvramSize;
-
-	/*
-	 * The following could fail if the NvRAM were corrupt but
-	 * we expect the boot firmware to have checked its checksum
-	 * before boot
-	 */
-	nvp = (char *) &nvram->Header;
-	for (i=0; i<sizeof(HEADER); i++)
-	{
-		*nvp = ppc_md.nvram_read_val(i);
-		nvp++;
-	}
-	
-	/*
-	 * The PReP NvRAM may be any size so read in the header to
-	 * determine how much we must read in order to get the complete
-	 * GE area
-	 */
-	nvramSize=(int)nvram->Header.GEAddress+nvram->Header.GELength;
-	if(nvramSize>MAX_PREP_NVRAM)
-	{
-		/*
-		 * NvRAM is too large
-		 */
-		nvram->Header.GELength=0;
-		return;
-	}
-
-	/*
-	 * Read the remainder of the PReP NvRAM
-	 */
-	nvp = (char *) &nvram->GEArea[0];
-	for (i=sizeof(HEADER); i<nvramSize; i++)
-	{
-		*nvp = ppc_md.nvram_read_val(i);
-		nvp++;
-	}
-}
-
-__prep
-char __prep *prep_nvram_get_var(const char *name)
-{
-	char *cp;
-	int  namelen;
-
-	namelen = strlen(name);
-	cp = prep_nvram_first_var();
-	while (cp != NULL) {
-		if ((strncmp(name, cp, namelen) == 0)
-		    && (cp[namelen] == '='))
-		{
-			return cp+namelen+1;
-		}
-		cp = prep_nvram_next_var(cp);
-	}
-
-	return NULL;
-}
-
-__prep
-char __prep *prep_nvram_first_var(void)
-{
-        if (nvram->Header.GELength == 0) {
-		return NULL;
-	} else {
-		return (((char *)nvram)
-			+ ((unsigned int) nvram->Header.GEAddress));
-	}
-}
-
-__prep
-char __prep *prep_nvram_next_var(char *name)
-{
-	char *cp;
-
-
-	cp = name;
-	while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
-	       && (*cp != '\0'))
-	{
-		cp++;
-	}
-
-	/* Skip over any null characters. */
-	while (((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength)
-	       && (*cp == '\0'))
-	{
-		cp++;
-	}
-
-	if ((cp - ((char *) nvram->GEArea)) < nvram->Header.GELength) {
-		return cp;
-	} else {
-		return NULL;
-	}
-}
-
-
-
diff -Nru a/arch/ppc/platforms/spruce_setup.c b/arch/ppc/platforms/spruce_setup.c
--- a/arch/ppc/platforms/spruce_setup.c	Thu Aug  1 14:17:36 2002
+++ b/arch/ppc/platforms/spruce_setup.c	Thu Aug  1 14:17:36 2002
@@ -6,7 +6,7 @@
  * Authors: Johnnie Peters <jpeters@mvista.com>
  *          Matt Porter <mporter@mvista.com>
  *
- * Copyright 2001 MontaVista Software Inc.
+ * Copyright 2001-2002 MontaVista Software Inc.
  *
  * 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
@@ -70,7 +70,7 @@
  *
  * First entry is the sensitivity (level/edge), second is the polarity.
  */
-unsigned int cpc700_irq_assigns[27][2] = {
+unsigned int cpc700_irq_assigns[32][2] = {
 	{ 1, 1 },       /* IRQ  0: ECC Correctable Error - rising edge */
 	{ 1, 1 },       /* IRQ  1: PCI Write Mem Range   - rising edge */
 	{ 0, 1 },       /* IRQ  2: PCI Write Command Reg - active high */
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	Thu Aug  1 14:17:41 2002
+++ b/arch/ppc64/kernel/Makefile	Thu Aug  1 14:17:41 2002
@@ -9,7 +9,7 @@
 O_TARGET	:= kernel.o
 EXTRA_TARGETS	:= $(KHEAD)
 
-export-objs         := ppc_ksyms.o setup.o
+export-objs         := ppc_ksyms.o
 
 obj-y               :=	ppc_ksyms.o setup.o entry.o traps.o irq.o idle.o \
 			time.o process.o signal.o syscalls.o misc.o ptrace.o \
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	Thu Aug  1 14:17:40 2002
+++ b/arch/ppc64/kernel/misc.S	Thu Aug  1 14:17:40 2002
@@ -916,8 +916,8 @@
 	.llong .sys_rt_sigtimedwait
 	.llong .sys_rt_sigqueueinfo
 	.llong .sys_rt_sigsuspend
-	.llong .sys_pread
-	.llong .sys_pwrite	        /* 180 */
+	.llong .sys_pread64
+	.llong .sys_pwrite64	        /* 180 */
 	.llong .sys_chown
 	.llong .sys_getcwd
 	.llong .sys_capget
diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
--- a/arch/s390/kernel/entry.S	Thu Aug  1 14:17:36 2002
+++ b/arch/s390/kernel/entry.S	Thu Aug  1 14:17:36 2002
@@ -520,8 +520,8 @@
         .long  sys_rt_sigtimedwait
         .long  sys_rt_sigqueueinfo
         .long  sys_rt_sigsuspend_glue
-        .long  sys_pread                 /* 180 */
-        .long  sys_pwrite
+        .long  sys_pread64               /* 180 */
+        .long  sys_pwrite64
         .long  sys_chown16
         .long  sys_getcwd
         .long  sys_capget
diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c
--- a/arch/s390/mm/init.c	Thu Aug  1 14:17:36 2002
+++ b/arch/s390/mm/init.c	Thu Aug  1 14:17:36 2002
@@ -189,7 +189,7 @@
 		totalram_pages++;
         }
         printk ("Freeing unused kernel memory: %dk freed\n",
-		(&__init_end - &__init_begin) >> 10);
+		((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c
--- a/arch/s390x/kernel/linux32.c	Thu Aug  1 14:17:36 2002
+++ b/arch/s390x/kernel/linux32.c	Thu Aug  1 14:17:36 2002
@@ -3980,10 +3980,10 @@
 }
 
 
-extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
+extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
 				    size_t count, loff_t pos);
 
-extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
+extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
 				     size_t count, loff_t pos);
 
 typedef __kernel_ssize_t32 ssize_t32;
@@ -3991,13 +3991,13 @@
 asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
 				 __kernel_size_t32 count, u32 poshi, u32 poslo)
 {
-	return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+	return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
 asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
 				  __kernel_size_t32 count, u32 poshi, u32 poslo)
 {
-	return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
 extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
diff -Nru a/arch/s390x/mm/init.c b/arch/s390x/mm/init.c
--- a/arch/s390x/mm/init.c	Thu Aug  1 14:17:40 2002
+++ b/arch/s390x/mm/init.c	Thu Aug  1 14:17:40 2002
@@ -201,7 +201,7 @@
 		totalram_pages++;
         }
         printk ("Freeing unused kernel memory: %ldk freed\n",
-		(&__init_end - &__init_begin) >> 10);
+		((unsigned long)&__init_end - (unsigned long)&__init_begin) >> 10);
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -Nru a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
--- a/arch/sh/kernel/Makefile	Thu Aug  1 14:17:40 2002
+++ b/arch/sh/kernel/Makefile	Thu Aug  1 14:17:40 2002
@@ -5,7 +5,8 @@
 O_TARGET	:= kernel.o
 EXTRA_TARGETS	:= head.o init_task.o
 
-export-objs	:= io.o io_generic.o io_hd64461.o setup_hd64461.o sh_ksyms.o
+export-objs	:= io.o io_generic.o io_hd64465.o setup_hd64465.o sh_ksyms.o \
+		   io_adx.o io_bigsur.o io_cat68701.o hd64465_gpio.o
 
 obj-y	:= process.o signal.o entry.o traps.o irq.o irq_ipr.o \
 	ptrace.o setup.o time.o sys_sh.o semaphore.o \
diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
--- a/arch/sparc/kernel/systbls.S	Thu Aug  1 14:17:40 2002
+++ b/arch/sparc/kernel/systbls.S	Thu Aug  1 14:17:40 2002
@@ -31,7 +31,7 @@
 /*50*/	.long sys_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys_ioctl
 /*55*/	.long sys_reboot, sys_mmap2, sys_symlink, sys_readlink, sys_execve
 /*60*/	.long sys_umask, sys_chroot, sys_newfstat, sys_fstat64, sys_getpagesize
-/*65*/	.long sys_msync, sys_vfork, sys_pread, sys_pwrite, sys_geteuid
+/*65*/	.long sys_msync, sys_vfork, sys_pread64, sys_pwrite64, sys_geteuid
 /*70*/	.long sys_getegid, sys_mmap, sys_setreuid, sys_munmap, sys_mprotect
 /*75*/	.long sys_madvise, sys_vhangup, sys_truncate64, sys_mincore, sys_getgroups16
 /*80*/	.long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64
diff -Nru a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
--- a/arch/sparc/mm/init.c	Thu Aug  1 14:17:40 2002
+++ b/arch/sparc/mm/init.c	Thu Aug  1 14:17:40 2002
@@ -18,7 +18,6 @@
 #include <linux/mman.h>
 #include <linux/mm.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
 #endif
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	Thu Aug  1 14:17:41 2002
+++ b/arch/sparc64/kernel/sys_sparc32.c	Thu Aug  1 14:17:41 2002
@@ -3878,10 +3878,10 @@
 }
 
 
-extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
+extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
 				    size_t count, loff_t pos);
 
-extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
+extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
 				     size_t count, loff_t pos);
 
 typedef __kernel_ssize_t32 ssize_t32;
@@ -3889,13 +3889,13 @@
 asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
 				 __kernel_size_t32 count, u32 poshi, u32 poslo)
 {
-	return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+	return sys_pread64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
 asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
 				  __kernel_size_t32 count, u32 poshi, u32 poslo)
 {
-	return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+	return sys_pwrite64(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
 extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
--- a/arch/sparc64/kernel/systbls.S	Thu Aug  1 14:17:40 2002
+++ b/arch/sparc64/kernel/systbls.S	Thu Aug  1 14:17:40 2002
@@ -32,7 +32,7 @@
 /*50*/	.word sys32_getegid16, sys_acct, sys_nis_syscall, sys_getgid, sys32_ioctl
 	.word sys_reboot, sys32_mmap2, sys_symlink, sys_readlink, sys32_execve
 /*60*/	.word sys_umask, sys_chroot, sys32_newfstat, sys_fstat64, sys_getpagesize
-	.word sys_msync, sys_vfork, sys32_pread, sys32_pwrite, sys_geteuid
+	.word sys_msync, sys_vfork, sys32_pread64, sys32_pwrite64, sys_geteuid
 /*70*/	.word sys_getegid, sys32_mmap, sys_setreuid, sys_munmap, sys_mprotect
 	.word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16
 /*80*/	.word sys32_setgroups16, sys_getpgrp, sys_setgroups, sys32_setitimer, sys32_ftruncate64
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Thu Aug  1 14:17:40 2002
+++ b/arch/sparc64/mm/init.c	Thu Aug  1 14:17:40 2002
@@ -15,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/pagemap.h>
 #include <linux/fs.h>
 #include <linux/seq_file.h>
diff -Nru a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
--- a/arch/sparc64/solaris/socksys.c	Thu Aug  1 14:17:40 2002
+++ b/arch/sparc64/solaris/socksys.c	Thu Aug  1 14:17:40 2002
@@ -181,7 +181,7 @@
 	int (*sys_close)(unsigned int) = 
 		(int (*)(unsigned int))SYS(close);
 	
-	ret = devfs_register_chrdev (30, "socksys", &socksys_fops);
+	ret = register_chrdev (30, "socksys", &socksys_fops);
 	if (ret < 0) {
 		printk ("Couldn't register socksys character device\n");
 		return ret;
@@ -208,7 +208,7 @@
 void
 cleanup_socksys(void)
 {
-	if (devfs_unregister_chrdev(30, "socksys"))
+	if (unregister_chrdev(30, "socksys"))
 		printk ("Couldn't unregister socksys character device\n");
 	devfs_unregister (devfs_handle);
 }
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	Thu Aug  1 14:17:40 2002
+++ b/arch/x86_64/ia32/sys_ia32.c	Thu Aug  1 14:17:40 2002
@@ -1948,10 +1948,10 @@
 	return ret;
 }
 
-extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
+extern asmlinkage ssize_t sys_pread64(unsigned int fd, char * buf,
 				    size_t count, loff_t pos);
 
-extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
+extern asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char * buf,
 				     size_t count, loff_t pos);
 
 typedef __kernel_ssize_t32 ssize_t32;
@@ -1961,7 +1961,7 @@
 sys32_pread(unsigned int fd, char *ubuf, __kernel_size_t32 count,
 	    u32 poslo, u32 poshi)
 {
-	return sys_pread(fd, ubuf, count,
+	return sys_pread64(fd, ubuf, count,
 			 ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
@@ -1969,7 +1969,7 @@
 sys32_pwrite(unsigned int fd, char *ubuf, __kernel_size_t32 count,
 	     u32 poslo, u32 poshi)
 {
-	return sys_pwrite(fd, ubuf, count,
+	return sys_pwrite64(fd, ubuf, count,
 			  ((loff_t)AA(poshi) << 32) | AA(poslo));
 }
 
diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
--- a/arch/x86_64/kernel/Makefile	Thu Aug  1 14:17:37 2002
+++ b/arch/x86_64/kernel/Makefile	Thu Aug  1 14:17:37 2002
@@ -5,7 +5,7 @@
 O_TARGET	:= kernel.o
 EXTRA_TARGETS 	:= head.o head64.o init_task.o
 
-export-objs     := mtrr.o msr.o cpuid.o x8664_ksyms.o
+export-objs     := mtrr.o x8664_ksyms.o
 
 obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o \
 		ptrace.o i8259.o ioport.o ldt.o setup.o time.o sys_x86_64.o \
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/Makefile	Thu Aug  1 14:17:41 2002
@@ -7,8 +7,9 @@
 
 obj-$(CONFIG_PCI)		+= pci/
 obj-$(CONFIG_ACPI)		+= acpi/
+obj-y				+= serial/
 obj-$(CONFIG_PARPORT)		+= parport/
-obj-y				+= base/ serial/ char/ block/ misc/ net/ media/
+obj-y				+= base/ char/ block/ misc/ net/ media/
 obj-$(CONFIG_NUBUS)		+= nubus/
 obj-$(CONFIG_ATM)		+= atm/
 obj-$(CONFIG_IDE)		+= ide/
diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c
--- a/drivers/acorn/block/mfmhd.c	Thu Aug  1 14:17:37 2002
+++ b/drivers/acorn/block/mfmhd.c	Thu Aug  1 14:17:37 2002
@@ -194,7 +194,6 @@
 #define MFM_DRV_INFO mfm_info[raw_cmd.dev]
 
 static struct hd_struct mfm[MFM_MAXDRIVES << 6];
-static int mfm_sizes[MFM_MAXDRIVES << 6];
 
 /* Stuff from the assembly routines */
 extern unsigned int hdc63463_baseaddress;	/* Controller base address */
@@ -1254,12 +1253,20 @@
 	}
 }
 
-static struct gendisk mfm_gendisk = {
+static struct gendisk mfm_gendisk[2] = {
+{
 	major:		MAJOR_NR,
+	first_minor:	0,
 	major_name:	"mfm",
 	minor_shift:	6,
 	part:		mfm,
-	sizes:		mfm_sizes,
+},
+{
+	major:		MAJOR_NR,
+	first_minor:	64,
+	major_name:	"mfm",
+	minor_shift:	6,
+	part:		mfm + 64,
 };
 
 static struct block_device_operations mfm_fops =
@@ -1277,8 +1284,6 @@
 
 	printk("mfm: detected %d hard drive%s\n", mfm_drives,
 				mfm_drives == 1 ? "" : "s");
-	mfm_gendisk.nr_real = mfm_drives;
-
 	if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
 		printk("mfm: unable to get IRQ%d\n", mfm_irq);
 
@@ -1286,8 +1291,10 @@
 		outw(0x80, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
 
 	for (i = 0; i < mfm_drives; i++) {
+		mfm_gendisk[i].nr_real = 1;
+		add_gendisk(mfm_gendisk + i);
 		mfm_geometry (i);
-		register_disk(&mfm_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6,
+		register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6,
 				&mfm_fops,
 				mfm_info[i].cylinders * mfm_info[i].heads *
 				mfm_info[i].sectors / 2);
@@ -1382,8 +1389,6 @@
 
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request);
 
-	add_gendisk(&mfm_gendisk);
-
 	Busy = 0;
 	lastspecifieddrive = -1;
 
@@ -1421,11 +1426,13 @@
 
 void cleanup_module(void)
 {
+	int i;
 	if (ecs && mfm_irqenable)
 		outw (0, mfm_irqenable);	/* Required to enable IRQs from MFM podule */
 	free_irq(mfm_irq, NULL);
 	unregister_blkdev(MAJOR_NR, "mfm");
-	del_gendisk(&mfm_gendisk);
+	for (i = 0; i < mfm_drives; i++)
+		del_gendisk(mfm_gendisk + i);
 	if (ecs)
 		ecard_release(ecs);
 	if (mfm_addr)
diff -Nru a/drivers/acorn/char/Makefile b/drivers/acorn/char/Makefile
--- a/drivers/acorn/char/Makefile	Thu Aug  1 14:17:36 2002
+++ b/drivers/acorn/char/Makefile	Thu Aug  1 14:17:36 2002
@@ -3,8 +3,6 @@
 #
 
 # All the objects that export symbols.
-export-objs	:= mouse_rpc.o
-
 obj-arc		:= keyb_arc.o
 obj-rpc		:= keyb_ps2.o
 obj-clps7500	:= keyb_ps2.o defkeymap-acorn.o
diff -Nru a/drivers/base/base.h b/drivers/base/base.h
--- a/drivers/base/base.h	Thu Aug  1 14:17:40 2002
+++ b/drivers/base/base.h	Thu Aug  1 14:17:40 2002
@@ -17,6 +17,7 @@
 extern void device_remove_dir(struct device * dev);
 
 extern int device_bus_link(struct device * dev);
+extern void device_remove_symlink(struct driver_dir_entry * dir, const char * name);
 
 extern int driver_attach(struct device_driver * drv);
 extern void driver_detach(struct device_driver * drv);
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/base/bus.c	Thu Aug  1 14:17:39 2002
@@ -140,7 +140,7 @@
 void bus_remove_device(struct device * dev)
 {
 	if (dev->bus) {
-		driverfs_remove_file(&dev->bus->device_dir,dev->bus_id);
+		device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
 		write_lock(&dev->bus->lock);
 		list_del_init(&dev->bus_list);
 		write_unlock(&dev->bus->lock);
diff -Nru a/drivers/base/fs.c b/drivers/base/fs.c
--- a/drivers/base/fs.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/base/fs.c	Thu Aug  1 14:17:40 2002
@@ -15,7 +15,63 @@
 #include <linux/stat.h>
 #include <linux/limits.h>
 
-extern struct driver_file_entry * device_default_files[];
+extern struct device_attribute * device_default_files[];
+
+#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+
+#define to_device(d) container_of(d, struct device, dir)
+
+
+/* driverfs ops for device attribute files */
+
+static int
+dev_attr_open(struct driver_dir_entry * dir)
+{
+	struct device * dev = to_device(dir);
+	get_device(dev);
+	return 0;
+}
+
+static int
+dev_attr_close(struct driver_dir_entry * dir)
+{
+	struct device * dev = to_device(dir);
+	put_device(dev);
+	return 0;
+}
+
+static ssize_t
+dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
+	      char * buf, size_t count, loff_t off)
+{
+	struct device_attribute * dev_attr = to_dev_attr(attr);
+	struct device * dev = to_device(dir);
+	ssize_t ret = 0;
+
+	if (dev_attr->show)
+		ret = dev_attr->show(dev,buf,count,off);
+	return ret;
+}
+
+static ssize_t
+dev_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
+	       const char * buf, size_t count, loff_t off)
+{
+	struct device_attribute * dev_attr = to_dev_attr(attr);
+	struct device * dev = to_device(dir);
+	ssize_t ret = 0;
+
+	if (dev_attr->store)
+		ret = dev_attr->store(dev,buf,count,off);
+	return ret;
+}
+
+static struct driverfs_ops dev_attr_ops = {
+	open:	dev_attr_open,
+	close:	dev_attr_close,
+	show:	dev_attr_show,
+	store:	dev_attr_store,
+};
 
 /**
  * device_create_file - create a driverfs file for a device
@@ -24,25 +80,15 @@
  *
  * Allocate space for file entry, copy descriptor, and create.
  */
-int device_create_file(struct device * dev, struct driver_file_entry * entry)
+int device_create_file(struct device * dev, struct device_attribute * entry)
 {
-	struct driver_file_entry * new_entry;
-	int error = -ENOMEM;
-
-	if (!dev)
-		return -EINVAL;
-	get_device(dev);
+	int error = -EINVAL;
 
-	new_entry = kmalloc(sizeof(*new_entry),GFP_KERNEL);
-	if (!new_entry)
-		goto done;
-
-	memcpy(new_entry,entry,sizeof(*entry));
-	error = driverfs_create_file(new_entry,&dev->dir);
-	if (error)
-		kfree(new_entry);
- done:
-	put_device(dev);
+	if (dev) {
+		get_device(dev);
+		error = driverfs_create_file(&entry->attr,&dev->dir);
+		put_device(dev);
+	}
 	return error;
 }
 
@@ -52,11 +98,11 @@
  * @name:	name of the file
  *
  */
-void device_remove_file(struct device * dev, const char * name)
+void device_remove_file(struct device * dev, struct device_attribute * attr)
 {
 	if (dev) {
 		get_device(dev);
-		driverfs_remove_file(&dev->dir,name);
+		driverfs_remove_file(&dev->dir,attr->attr.name);
 		put_device(dev);
 	}
 }
@@ -71,7 +117,6 @@
 		driverfs_remove_dir(&dev->dir);
 }
 
-
 static int get_devpath_length(struct device * dev)
 {
 	int length = 1;
@@ -103,22 +148,6 @@
 	pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
 }
 
-static int create_symlink(struct driver_dir_entry * parent, char * name, char * path)
-{
-	struct driver_file_entry * entry;
-	int error;
-
-	entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL);
-	if (!entry)
-		return -ENOMEM;
-	entry->name = name;
-	entry->mode = S_IRUGO;
-	error = driverfs_create_symlink(parent,entry,path);
-	if (error)
-		kfree(entry);
-	return error;
-}
-
 int device_bus_link(struct device * dev)
 {
 	char * path;
@@ -148,15 +177,18 @@
 	strcpy(path,"../../..");
 
 	fill_devpath(dev,path,length);
-	error = create_symlink(&dev->bus->device_dir,dev->bus_id,path);
-
+	error = driverfs_create_symlink(&dev->bus->device_dir,dev->bus_id,path);
 	kfree(path);
 	return error;
 }
 
+void device_remove_symlink(struct driver_dir_entry * dir, const char * name)
+{
+	driverfs_remove_file(dir,name);
+}
+
 int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent)
 {
-	INIT_LIST_HEAD(&dir->files);
 	dir->mode  = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
 	return driverfs_create_dir(dir,parent);
 }
@@ -176,13 +208,14 @@
 int device_make_dir(struct device * dev)
 {
 	struct driver_dir_entry * parent = NULL;
-	struct driver_file_entry * entry;
+	struct device_attribute * entry;
 	int error;
 	int i;
 
 	if (dev->parent)
 		parent = &dev->parent->dir;
 	dev->dir.name = dev->bus_id;
+	dev->dir.ops = &dev_attr_ops;
 
 	if ((error = device_create_dir(&dev->dir,parent)))
 		return error;
diff -Nru a/drivers/base/interface.c b/drivers/base/interface.c
--- a/drivers/base/interface.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/base/interface.c	Thu Aug  1 14:17:36 2002
@@ -14,11 +14,7 @@
 	return off ? 0 : sprintf(buf,"%s\n",dev->name);
 }
 
-static struct driver_file_entry device_name_entry = {
-	name:	"name",
-	mode:	S_IRUGO,
-	show:	device_read_name,
-};
+static DEVICE_ATTR(name,"name",S_IRUGO,device_read_name,NULL);
 
 static ssize_t
 device_read_power(struct device * dev, char * page, size_t count, loff_t off)
@@ -89,15 +85,11 @@
 	return error < 0 ? error : count;
 }
 
-static struct driver_file_entry device_power_entry = {
-	name:		"power",
-	mode:		S_IWUSR | S_IRUGO,
-	show:		device_read_power,
-	store:		device_write_power,
-};
-
-struct driver_file_entry * device_default_files[] = {
-	&device_name_entry,
-	&device_power_entry,
+static DEVICE_ATTR(power,"power",S_IWUSR | S_IRUGO,
+		   device_read_power,device_write_power);
+
+struct device_attribute * device_default_files[] = {
+	&dev_attr_name,
+	&dev_attr_power,
 	NULL,
 };
diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c
--- a/drivers/block/DAC960.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/DAC960.c	Thu Aug  1 14:17:41 2002
@@ -1934,7 +1934,7 @@
   /*
     Register the Block Device Major Number for this DAC960 Controller.
   */
-  if (devfs_register_blkdev(MajorNumber, "dac960",
+  if (register_blkdev(MajorNumber, "dac960",
 			    &DAC960_BlockDeviceOperations) < 0)
     {
       DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n",
@@ -1961,7 +1961,6 @@
     Controller->MaxSectorsPerRequest[MinorNumber] =
       Controller->MaxBlocksPerCommand;
   Controller->GenericDiskInfo.part = Controller->DiskPartitions;
-  Controller->GenericDiskInfo.sizes = Controller->PartitionSizes;
   /*
     Complete initialization of the Generic Disk Information structure.
   */
@@ -1993,7 +1992,7 @@
   /*
     Unregister the Block Device Major Number for this DAC960 Controller.
   */
-  devfs_unregister_blkdev(MajorNumber, "dac960");
+  unregister_blkdev(MajorNumber, "dac960");
   /*
     Remove the I/O Request Queue.
   */
@@ -2003,7 +2002,6 @@
     array, Max Sectors per Request array, and Max Segments per Request array.
   */
   Controller->GenericDiskInfo.part = NULL;
-  Controller->GenericDiskInfo.sizes = NULL;
   blk_clear(MajorNumber);
   /*
     Remove the Generic Disk Information structure from the list.
@@ -5295,7 +5293,7 @@
       DAC960_ComputeGenericDiskInfo(Controller);
       DAC960_RegisterDisk(Controller, LogicalDriveNumber);
     }
-  if (Controller->GenericDiskInfo.sizes[minor(Inode->i_rdev)] == 0)
+  if (Controller->GenericDiskInfo.part[minor(Inode->i_rdev)].nr_sects == 0)
     return -ENXIO;
   /*
     Increment Controller and Logical Drive Usage Counts.
diff -Nru a/drivers/block/DAC960.h b/drivers/block/DAC960.h
--- a/drivers/block/DAC960.h	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/DAC960.h	Thu Aug  1 14:17:41 2002
@@ -2473,7 +2473,6 @@
     } V2;
   } FW;
   DiskPartition_T DiskPartitions[DAC960_MinorCount];
-  int PartitionSizes[DAC960_MinorCount];
   unsigned char ProgressBuffer[DAC960_ProgressBufferSize];
   unsigned char UserStatusBuffer[DAC960_UserMessageSize];
 }
diff -Nru a/drivers/block/Makefile b/drivers/block/Makefile
--- a/drivers/block/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/Makefile	Thu Aug  1 14:17:41 2002
@@ -8,7 +8,8 @@
 # In the future, some of these should be built conditionally.
 #
 
-export-objs	:= elevator.o ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o block_ioctl.o
+export-objs	:= elevator.o ll_rw_blk.o blkpg.o loop.o genhd.o \
+		   block_ioctl.o acsi.o
 
 obj-y	:= elevator.o ll_rw_blk.o blkpg.o genhd.o block_ioctl.o
 
diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c
--- a/drivers/block/acsi.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/block/acsi.c	Thu Aug  1 14:17:40 2002
@@ -56,7 +56,6 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/genhd.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/major.h>
@@ -246,7 +245,6 @@
 unsigned long 	phys_acsi_buffer;
 
 static int				NDevices = 0;
-static int				acsi_sizes[MAX_DEV<<4] = { 0, };
 static struct hd_struct	acsi_part[MAX_DEV<<4] = { {0,0}, };
 static int 				access_count[MAX_DEV] = { 0, };
 
@@ -1360,7 +1358,6 @@
 	major_name:	"ad",
 	minor_shift:	4,
 	part:		acsi_part,
-	sizes:		acsi_sizes,
 	fops:		&acsi_fops,
 };
 	
@@ -1741,14 +1738,14 @@
 	int err = 0;
 	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI))
 		return 0;
-	if (devfs_register_blkdev( MAJOR_NR, "ad", &acsi_fops )) {
+	if (register_blkdev( MAJOR_NR, "ad", &acsi_fops )) {
 		printk( KERN_ERR "Unable to get major %d for ACSI\n", MAJOR_NR );
 		return -EBUSY;
 	}
 	if (!(acsi_buffer =
 		  (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) {
 		printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" );
-		devfs_unregister_blkdev( MAJOR_NR, "ad" );
+		unregister_blkdev( MAJOR_NR, "ad" );
 		return -ENOMEM;
 	}
 	phys_acsi_buffer = virt_to_phys( acsi_buffer );
@@ -1786,7 +1783,7 @@
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	atari_stram_free( acsi_buffer );
 
-	if (devfs_unregister_blkdev( MAJOR_NR, "ad" ) != 0)
+	if (unregister_blkdev( MAJOR_NR, "ad" ) != 0)
 		printk( KERN_ERR "acsi: cleanup_module failed\n");
 
 	del_gendisk(&acsi_gendisk);
diff -Nru a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
--- a/drivers/block/acsi_slm.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/acsi_slm.c	Thu Aug  1 14:17:36 2002
@@ -998,14 +998,14 @@
 int slm_init( void )
 
 {
-	if (devfs_register_chrdev( MAJOR_NR, "slm", &slm_fops )) {
+	if (register_chrdev( MAJOR_NR, "slm", &slm_fops )) {
 		printk( KERN_ERR "Unable to get major %d for ACSI SLM\n", MAJOR_NR );
 		return -EBUSY;
 	}
 	
 	if (!(SLMBuffer = atari_stram_alloc( SLM_BUFFER_SIZE, NULL, "SLM" ))) {
 		printk( KERN_ERR "Unable to get SLM ST-Ram buffer.\n" );
-		devfs_unregister_chrdev( MAJOR_NR, "slm" );
+		unregister_chrdev( MAJOR_NR, "slm" );
 		return -ENOMEM;
 	}
 	BufferP = SLMBuffer;
@@ -1038,7 +1038,7 @@
 void cleanup_module(void)
 {
 	devfs_unregister (devfs_handle);
-	if (devfs_unregister_chrdev( MAJOR_NR, "slm" ) != 0)
+	if (unregister_chrdev( MAJOR_NR, "slm" ) != 0)
 		printk( KERN_ERR "acsi_slm: cleanup_module failed\n");
 	atari_stram_free( SLMBuffer );
 }
diff -Nru a/drivers/block/blkpg.c b/drivers/block/blkpg.c
--- a/drivers/block/blkpg.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/blkpg.c	Thu Aug  1 14:17:36 2002
@@ -86,7 +86,7 @@
 	g = get_gendisk(dev);
 	if (!g)
 		return -ENXIO;
-	part = g->part + minor(dev);
+	part = g->part + minor(dev) - g->first_minor;
 
 	/* existing drive? */
 
@@ -109,8 +109,6 @@
 	/* all seems OK */
 	part[p->pno].start_sect = pstart;
 	part[p->pno].nr_sects = plength;
-	if (g->sizes)
-		g->sizes[minor(dev)+p->pno] = (plength >> (BLOCK_SIZE_BITS-9));
 	devfs_register_partitions (g, minor(dev), 0);
 	return 0;
 }
@@ -137,7 +135,7 @@
 	g = get_gendisk(dev);
 	if (!g)
 		return -ENXIO;
-	part = g->part + minor(dev);
+	part = g->part + minor(dev) - g->first_minor;
 
 	if (bdev != bdev->bd_contains)
 		return -EINVAL;
@@ -163,8 +161,6 @@
 
 	part[p->pno].start_sect = 0;
 	part[p->pno].nr_sects = 0;
-	if (g->sizes)
-		g->sizes[minor(dev) + p->pno] = 0;
 	devfs_register_partitions (g, minor(dev), 0);
 	bd_release(bdevp);
 	bdput(bdevp);
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/cciss.c	Thu Aug  1 14:17:41 2002
@@ -348,8 +348,7 @@
 		drv = &(hba[ctlr]->drv[i]);
 		if( !(drv->nr_blocks))
 			continue;
-		hba[ctlr]->hd[i << NWD_SHIFT].nr_sects = 
-		hba[ctlr]->sizes[i << NWD_SHIFT] = drv->nr_blocks;
+		hba[ctlr]->hd[i << NWD_SHIFT].nr_sects = drv->nr_blocks;
 		//hba[ctlr]->gendisk.nr_real++;
 		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->block_size;
 	}
@@ -375,7 +374,7 @@
 	 * but I'm already using way to many device nodes to claim another one
 	 * for "raw controller".
 	 */
-	if (hba[ctlr]->sizes[minor(inode->i_rdev)] == 0) {
+	if (inode->i_bdev->bd_inode->i_size == 0) {
 		if (minor(inode->i_rdev) != 0)
 			return -ENXIO;
 		if (!capable(CAP_SYS_ADMIN))
@@ -806,7 +805,6 @@
          * on this controller to zero.  We will reread all of this data
          */
 	memset(hba[ctlr]->hd,         0, sizeof(struct hd_struct) * 256);
-        memset(hba[ctlr]->sizes,      0, sizeof(int) * 256);
         memset(hba[ctlr]->drv,        0, sizeof(drive_info_struct)
 						* CISS_MAX_LUN);
         hba[ctlr]->gendisk.nr_real = 0;
@@ -823,7 +821,7 @@
         cciss_geninit(ctlr);
         for(i=0; i<NWD; i++) {
 		kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
-                if (hba[ctlr]->sizes[ i<<NWD_SHIFT ])
+                if (hba[ctlr]->gendisk.part[ i<<NWD_SHIFT ].nr_sects)
                         revalidate_logvol(kdev, 2);
 	}
 
@@ -836,7 +834,7 @@
 	unsigned long flags;
 	struct gendisk *gdev = &(hba[ctlr]->gendisk);
 	ctlr_info_t  *h = hba[ctlr];
-	int start, max_p, i;	
+	int start, max_p;
 
 
 	if (!capable(CAP_SYS_RAWIO))
@@ -856,8 +854,6 @@
 	max_p = 1 << gdev->minor_shift;
 	start = logvol << gdev->minor_shift;
 	wipe_partitions(mk_kdev(MAJOR_NR+ctlr, start));
-	for (i=max_p-1; i>=0; i--)
-		h->sizes[start + i] = 0;
 	/* check to see if it was the last disk */
 	if (logvol == h->highest_lun)
 	{
@@ -866,7 +862,7 @@
 		for(i=0; i<h->highest_lun; i++)
 		{
 			/* if the disk has size > 0, it is available */
-			if (h->sizes[i << gdev->minor_shift] != 0)
+			if (h->gendisk.part[i << gdev->minor_shift].nr_sects)
 				newhighest = i;
 		}
 		h->highest_lun = newhighest;
@@ -2498,7 +2494,6 @@
 	hba[i]->gendisk.major_name = "cciss";
 	hba[i]->gendisk.minor_shift = NWD_SHIFT;
 	hba[i]->gendisk.part = hba[i]->hd;
-	hba[i]->gendisk.sizes = hba[i]->sizes;
 	hba[i]->gendisk.nr_real = hba[i]->highest_lun+1;  
 
 	/* Get on the disk list */ 
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/cpqarray.c	Thu Aug  1 14:17:36 2002
@@ -104,7 +104,6 @@
 };
 
 static struct hd_struct * ida;
-static int * ida_sizes;
 static struct gendisk ida_gendisk[MAX_CTLR];
 
 static struct proc_dir_entry *proc_array;
@@ -176,9 +175,7 @@
 		drv = &hba[ctlr]->drv[i];
 		if (!drv->nr_blks)
 			continue;
-		ida[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)].nr_sects =
-		ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)] =
-				drv->nr_blks;
+		ida[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)].nr_sects = drv->nr_blks;
 
 		(BLK_DEFAULT_QUEUE(MAJOR_NR + ctlr))->hardsect_size = drv->blk_size;
 		ida_gendisk[ctlr].nr_real++;
@@ -336,10 +333,9 @@
 
 		del_gendisk(&ida_gendisk[i]);
 	}
-	devfs_unregister(devfs_find_handle(NULL, "ida", 0, 0, 0, 0));
+	devfs_find_and_unregister(NULL, "ida", 0, 0, 0, 0);
 	remove_proc_entry("cpqarray", proc_root_driver);
 	kfree(ida);
-	kfree(ida_sizes);
 }
 #endif /* MODULE */
 
@@ -372,16 +368,7 @@
 		return(num_cntlrs_reg);
 	}
 	
-	ida_sizes = kmalloc(sizeof(int)*nr_ctlr*NWD*16, GFP_KERNEL);
-	if(ida_sizes==NULL)
-	{
-		kfree(ida); 
-		printk( KERN_ERR "cpqarray: out of memory");
-		return(num_cntlrs_reg);
-	}
-
 	memset(ida, 0, sizeof(struct hd_struct)*nr_ctlr*NWD*16);
-	memset(ida_sizes, 0, sizeof(int)*nr_ctlr*NWD*16);
 	memset(ida_gendisk, 0, sizeof(struct gendisk)*MAX_CTLR);
 
 		/* 
@@ -437,7 +424,6 @@
 			if (num_cntlrs_reg == 0) 
 			{
 				kfree(ida);
-				kfree(ida_sizes);
 			}
                 	return(num_cntlrs_reg);
 	
@@ -469,7 +455,6 @@
 		ida_gendisk[i].major_name = "ida";
 		ida_gendisk[i].minor_shift = NWD_SHIFT;
 		ida_gendisk[i].part = ida + (i*256);
-		ida_gendisk[i].sizes = ida_sizes + (i*256);
 		ida_gendisk[i].nr_real = 0; 
 		ida_gendisk[i].de_arr = de_arr[i]; 
 		ida_gendisk[i].fops = &ida_fops; 
@@ -770,8 +755,7 @@
 	if (ctlr > MAX_CTLR || hba[ctlr] == NULL)
 		return -ENXIO;
 
-	if (!capable(CAP_SYS_RAWIO) && ida_sizes[(ctlr << CTLR_SHIFT) +
-						minor(inode->i_rdev)] == 0)
+	if (!capable(CAP_SYS_RAWIO) && inode->i_bdev->bd_inode->i_size == 0)
 		return -ENXIO;
 
 	/*
@@ -781,7 +765,7 @@
 	 * for "raw controller".
 	 */
 	if (capable(CAP_SYS_ADMIN)
-		&& ida_sizes[(ctlr << CTLR_SHIFT) + minor(inode->i_rdev)] == 0 
+		&& inode->i_bdev->bd_inode->i_size == 0
 		&& minor(inode->i_rdev) != 0)
 		return -ENXIO;
 
@@ -1498,7 +1482,6 @@
 	 * on this controller to zero.  We will reread all of this data
 	 */
 	memset(ida+(ctlr*256),            0, sizeof(struct hd_struct)*NWD*16);
-	memset(ida_sizes+(ctlr*256),      0, sizeof(int)*NWD*16);
 	memset(hba[ctlr]->drv,            0, sizeof(drv_info_t)*NWD);
 	ida_gendisk[ctlr].nr_real = 0;
 
@@ -1514,7 +1497,7 @@
 	ida_geninit(ctlr);
 	for(i=0; i<NWD; i++) {
 		kdev_t kdev = mk_kdev(major(dev), i << NWD_SHIFT);
-		if (ida_sizes[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)])
+		if (ida[(ctlr<<CTLR_SHIFT) + (i<<NWD_SHIFT)].nr_sects)
 			revalidate_logvol(kdev, 2);
 	}
 
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/elevator.c	Thu Aug  1 14:17:41 2002
@@ -220,7 +220,8 @@
 	}
 }
 
-void elevator_linus_merge_req(struct request *req, struct request *next)
+void elevator_linus_merge_req(request_queue_t *q, struct request *req,
+			      struct request *next)
 {
 	if (elv_linus_sequence(next) < elv_linus_sequence(req))
 		elv_linus_sequence(req) = elv_linus_sequence(next);
@@ -232,6 +233,9 @@
 	elevator_t *e = &q->elevator;
 	int lat = 0, *latency = e->elevator_data;
 
+	if (!insert_here)
+		insert_here = q->queue_head.prev;
+
 	if (!(rq->flags & REQ_BARRIER))
 		lat = latency[rq_data_dir(rq)];
 
@@ -318,7 +322,7 @@
 
 struct request *elevator_noop_next_request(request_queue_t *q)
 {
-	if (!blk_queue_empty(q))
+	if (!list_empty(&q->queue_head))
 		return list_entry_rq(q->queue_head.next);
 
 	return NULL;
@@ -376,7 +380,7 @@
 	elevator_t *e = &q->elevator;
 
 	if (e->elevator_merge_req_fn)
-		e->elevator_merge_req_fn(rq, next);
+		e->elevator_merge_req_fn(q, rq, next);
 }
 
 /*
@@ -431,6 +435,27 @@
 
 	if (e->elevator_remove_req_fn)
 		e->elevator_remove_req_fn(q, rq);
+}
+
+int elv_queue_empty(request_queue_t *q)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_queue_empty_fn)
+		return e->elevator_queue_empty_fn(q);
+
+	return list_empty(&q->queue_head);
+}
+
+inline struct list_head *elv_get_sort_head(request_queue_t *q,
+					   struct request *rq)
+{
+	elevator_t *e = &q->elevator;
+
+	if (e->elevator_get_sort_head_fn)
+		return e->elevator_get_sort_head_fn(q, rq);
+
+	return &q->queue_head;
 }
 
 elevator_t elevator_linus = {
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/floppy.c	Thu Aug  1 14:17:36 2002
@@ -4233,7 +4233,7 @@
 	raw_cmd = NULL;
 
 	devfs_handle = devfs_mk_dir (NULL, "floppy", NULL);
-	if (devfs_register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
+	if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
 		printk("Unable to get major %d for floppy\n",MAJOR_NR);
 		return -EBUSY;
 	}
@@ -4266,7 +4266,7 @@
 	use_virtual_dma = can_use_virtual_dma & 1;
 	fdc_state[0].address = FDC1;
 	if (fdc_state[0].address == -1) {
-		devfs_unregister_blkdev(MAJOR_NR,"fd");
+		unregister_blkdev(MAJOR_NR,"fd");
 		del_timer(&fd_timeout);
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		return -ENODEV;
@@ -4279,7 +4279,7 @@
 	if (floppy_grab_irq_and_dma()){
 		del_timer(&fd_timeout);
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-		devfs_unregister_blkdev(MAJOR_NR,"fd");
+		unregister_blkdev(MAJOR_NR,"fd");
 		return -EBUSY;
 	}
 
@@ -4342,7 +4342,7 @@
 		if (usage_count)
 			floppy_release_irq_and_dma();
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-		devfs_unregister_blkdev(MAJOR_NR,"fd");
+		unregister_blkdev(MAJOR_NR,"fd");
 	}
 	
 	for (drive = 0; drive < N_DRIVE; drive++) {
@@ -4539,7 +4539,7 @@
 	int dummy;
 		
 	devfs_unregister (devfs_handle);
-	devfs_unregister_blkdev(MAJOR_NR, "fd");
+	unregister_blkdev(MAJOR_NR, "fd");
 
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	/* eject disk, if any */
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/block/genhd.c	Thu Aug  1 14:17:40 2002
@@ -55,8 +55,8 @@
 	{
 		if (sgp == gp)
 		{
-//			printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
-//				sgp->major)
+			printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
+				sgp->major);
 			goto out;
 		}
 	}
@@ -104,15 +104,22 @@
 get_gendisk(kdev_t dev)
 {
 	struct gendisk *gp = NULL;
-	int maj = major(dev);
+	int major = major(dev);
+	int minor = minor(dev);
 
 	read_lock(&gendisk_lock);
-	for (gp = gendisk_head; gp; gp = gp->next)
-		if (gp->major == maj)
-			break;
+	for (gp = gendisk_head; gp; gp = gp->next) {
+		if (gp->major != major)
+			continue;
+		if (gp->first_minor > minor)
+			continue;
+		if (gp->first_minor + (1<<gp->minor_shift) <= minor)
+			continue;
+		read_unlock(&gendisk_lock);
+		return gp;
+	}
 	read_unlock(&gendisk_lock);
-
-	return gp;
+	return NULL;
 }
 
 EXPORT_SYMBOL(get_gendisk);
@@ -157,9 +164,10 @@
 		int minormask = (1<<sgp->minor_shift) - 1;
 		if ((n & minormask) && sgp->part[n].nr_sects == 0)
 			continue;
-		seq_printf(part, "%4d  %4d %10d %s\n",
-			sgp->major, n, sgp->sizes[n],
-			disk_name(sgp, n, buf));
+		seq_printf(part, "%4d  %4d %10ld %s\n",
+			sgp->major, n + sgp->first_minor,
+			sgp->part[n].nr_sects << 1,
+			disk_name(sgp, n + sgp->first_minor, buf));
 	}
 
 	return 0;
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/ll_rw_blk.c	Thu Aug  1 14:17:36 2002
@@ -1253,7 +1253,7 @@
  *    host that is unable to accept a particular command.
  */
 void blk_insert_request(request_queue_t *q, struct request *rq,
-		int at_head, void *data)
+			int at_head, void *data)
 {
 	unsigned long flags;
 
@@ -1262,15 +1262,18 @@
 	 * must not attempt merges on this) and that it acts as a soft
 	 * barrier
 	 */
-	rq->flags &= REQ_QUEUED;
 	rq->flags |= REQ_SPECIAL | REQ_BARRIER;
 
 	rq->special = data;
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	/* If command is tagged, release the tag */
-	if(blk_rq_tagged(rq))
+
+	/*
+	 * If command is tagged, release the tag
+	 */
+	if (blk_rq_tagged(rq))
 		blk_queue_end_tag(q, rq);
+
 	_elv_add_request(q, rq, !at_head, 0);
 	q->request_fn(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
@@ -1388,7 +1391,6 @@
 
 	if (rq_data_dir(req) != rq_data_dir(next)
 	    || !kdev_same(req->rq_dev, next->rq_dev)
-	    || req->nr_sectors + next->nr_sectors > q->max_sectors
 	    || next->waiting || next->special)
 		return;
 
@@ -1399,15 +1401,14 @@
 	 * counts here.
 	 */
 	if (q->merge_requests_fn(q, req, next)) {
-		elv_merge_requests(q, req, next);
-
-		blkdev_dequeue_request(next);
-
 		req->biotail->bi_next = next->bio;
 		req->biotail = next->biotail;
 
 		req->nr_sectors = req->hard_nr_sectors += next->hard_nr_sectors;
 
+		elv_merge_requests(q, req, next);
+
+		blkdev_dequeue_request(next);
 		blk_put_request(next);
 	}
 }
@@ -1415,16 +1416,18 @@
 static inline void attempt_back_merge(request_queue_t *q, struct request *rq)
 {
 	struct list_head *next = rq->queuelist.next;
+	struct list_head *sort_head = elv_get_sort_head(q, rq);
 
-	if (next != &q->queue_head)
+	if (next != sort_head)
 		attempt_merge(q, rq, list_entry_rq(next));
 }
 
 static inline void attempt_front_merge(request_queue_t *q, struct request *rq)
 {
 	struct list_head *prev = rq->queuelist.prev;
+	struct list_head *sort_head = elv_get_sort_head(q, rq);
 
-	if (prev != &q->queue_head)
+	if (prev != sort_head)
 		attempt_merge(q, list_entry_rq(prev), rq);
 }
 
@@ -1484,7 +1487,7 @@
 	spin_lock_irq(q->queue_lock);
 again:
 	req = NULL;
-	insert_here = q->queue_head.prev;
+	insert_here = NULL;
 
 	if (blk_queue_empty(q)) {
 		blk_plug_device(q);
@@ -1502,11 +1505,10 @@
 				break;
 			}
 
-			elv_merge_cleanup(q, req, nr_sectors);
-
 			req->biotail->bi_next = bio;
 			req->biotail = bio;
 			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+			elv_merge_cleanup(q, req, nr_sectors);
 			drive_stat_acct(req, nr_sectors, 0);
 			attempt_back_merge(q, req);
 			goto out;
@@ -1518,8 +1520,6 @@
 				break;
 			}
 
-			elv_merge_cleanup(q, req, nr_sectors);
-
 			bio->bi_next = req->bio;
 			req->bio = bio;
 			/*
@@ -1532,6 +1532,7 @@
 			req->hard_cur_sectors = cur_nr_sectors;
 			req->sector = req->hard_sector = sector;
 			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+			elv_merge_cleanup(q, req, nr_sectors);
 			drive_stat_acct(req, nr_sectors, 0);
 			attempt_front_merge(q, req);
 			goto out;
@@ -1600,9 +1601,7 @@
 	req->buffer = bio_data(bio);	/* see ->buffer comment above */
 	req->waiting = NULL;
 	req->bio = req->biotail = bio;
-	if (bio->bi_bdev)
-		req->rq_dev = to_kdev_t(bio->bi_bdev->bd_dev);
-	else	req->rq_dev = NODEV;
+	req->rq_dev = to_kdev_t(bio->bi_bdev->bd_dev);
 	add_request(q, req, insert_here);
 out:
 	if (freereq)
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/loop.c	Thu Aug  1 14:17:36 2002
@@ -1027,7 +1027,7 @@
 		max_loop = 8;
 	}
 
-	if (devfs_register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
+	if (register_blkdev(MAJOR_NR, "loop", &lo_fops)) {
 		printk(KERN_WARNING "Unable to get major number %d for loop"
 				    " device\n", MAJOR_NR);
 		return -EIO;
@@ -1078,7 +1078,7 @@
 void loop_exit(void) 
 {
 	devfs_unregister(devfs_handle);
-	if (devfs_unregister_blkdev(MAJOR_NR, "loop"))
+	if (unregister_blkdev(MAJOR_NR, "loop"))
 		printk(KERN_WARNING "loop: cannot unregister blkdev\n");
 
 	kfree(loop_dev);
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/paride/pd.c	Thu Aug  1 14:17:41 2002
@@ -272,7 +272,6 @@
 static void pd_eject( int unit);
 
 static struct hd_struct pd_hd[PD_DEVS];
-static int pd_sizes[PD_DEVS];
 
 #define PD_NAMELEN	8
 
@@ -292,6 +291,7 @@
 	int alt_geom;
 	int present;
 	char name[PD_NAMELEN];		/* pda, pdb, etc ... */
+	struct gendisk gd;
 };
 
 struct pd_unit pd[PD_UNITS];
@@ -331,9 +331,8 @@
 	major:		PD_MAJOR,
 	major_name:	PD_NAME,
 	minor_shift:	PD_BITS,
-	part:		pd_hd,
-	sizes:		pd_sizes,
 	fops:		&pd_fops,
+	nr_real:	1,
 };
 
 static struct block_device_operations pd_fops = {
@@ -682,8 +681,8 @@
 }
 
 static int pd_detect( void )
-
-{       int	k, unit;
+{
+	int	k, unit;
 
 	k = 0;
 	if (pd_drive_count == 0) {  /* nothing spec'd - so autoprobe for 1 */
@@ -705,18 +704,19 @@
                         k = unit+1;
                 } else pi_release(PI);
             }
-	for (unit=0;unit<PD_UNITS;unit++)
-		register_disk(&pd_gendisk,mk_kdev(MAJOR_NR,unit<<PD_BITS),
-				PD_PARTNS,&pd_fops,
-				PD.present?PD.capacity:0);
-
-/* We lie about the number of drives found, as the generic partition
-   scanner assumes that the drives are numbered sequentially from 0.
-   This can result in some bogus error messages if non-sequential
-   drive numbers are used.
-*/
+	for (unit=0;unit<PD_UNITS;unit++) {
+		if (PD.present) {
+			PD.gd = pd_gendisk;
+			PD.gd.first_minor = unit << PD_BITS;
+			PD.gd.part = pd_hd + (unit << PD_BITS);
+			add_gendisk(&PD.gd);
+			register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS),
+					PD_PARTNS,&pd_fops,
+					PD.capacity);
+		}
+	}
 	if (k)
-		return k; 
+		return 1; 
         printk("%s: no valid drive found\n",name);
         return 0;
 }
@@ -937,10 +937,8 @@
 static int __init pd_init(void)
 {
 	request_queue_t * q;
-	int unit;
-
 	if (disable) return -1;
-        if (devfs_register_blkdev(MAJOR_NR,name,&pd_fops)) {
+        if (register_blkdev(MAJOR_NR,name,&pd_fops)) {
                 printk("%s: unable to get major number %d\n",
                         name,major);
                 return -1;
@@ -951,18 +949,11 @@
 
 	pd_gendisk.major = major;
 	pd_gendisk.major_name = name;
-	add_gendisk(&pd_gendisk);
-
 	printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
 		name,name,PD_VERSION,major,cluster,nice);
 	pd_init_units();
-	pd_gendisk.nr_real = pd_detect();
-        if (!pd_gendisk.nr_real) {
-		devfs_unregister_blkdev(MAJOR_NR, name);
-		del_gendisk(&pd_gendisk);
-		for (unit=0; unit<PD_UNITS; unit++) 
-			if (PD.present)
-				pi_release(PI);
+        if (!pd_detect()) {
+		unregister_blkdev(MAJOR_NR, name);
 		return -1;
 	}
         return 0;
@@ -971,11 +962,12 @@
 static void __exit pd_exit(void)
 {
 	int unit;
-	devfs_unregister_blkdev(MAJOR_NR, name);
-	del_gendisk(&pd_gendisk);
+	unregister_blkdev(MAJOR_NR, name);
 	for (unit=0; unit<PD_UNITS; unit++) 
-		if (PD.present)
+		if (PD.present) {
+			del_gendisk(&PD.gd);
 			pi_release(PI);
+		}
 }
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
--- a/drivers/block/paride/pg.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/paride/pg.c	Thu Aug  1 14:17:41 2002
@@ -637,7 +637,7 @@
 	if (pg_detect())
 		return -1;
 
-	if (devfs_register_chrdev(major,name,&pg_fops)) {
+	if (register_chrdev(major,name,&pg_fops)) {
 		printk("pg_init: unable to get major number %d\n",
 			major);
 		for (unit=0;unit<PG_UNITS;unit++)
@@ -656,7 +656,7 @@
 	int unit;
 
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev(major,name);
+	unregister_chrdev(major,name);
 
 	for (unit=0;unit<PG_UNITS;unit++)
 		if (PG.present) pi_release(PI);
diff -Nru a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
--- a/drivers/block/paride/pt.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/block/paride/pt.c	Thu Aug  1 14:17:39 2002
@@ -907,7 +907,7 @@
 	if (pt_detect())
 		return -1;
 
-	if (devfs_register_chrdev(major,name,&pt_fops)) {
+	if (register_chrdev(major,name,&pt_fops)) {
 		printk("pt_init: unable to get major number %d\n",
 			major);
 		for (unit=0;unit<PT_UNITS;unit++)
@@ -929,7 +929,7 @@
 {
 	int unit;
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev(major,name);
+	unregister_chrdev(major,name);
 	for (unit=0;unit<PT_UNITS;unit++)
 		if (PT.present)
 			pi_release(PI);
diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
--- a/drivers/block/ps2esdi.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/block/ps2esdi.c	Thu Aug  1 14:17:36 2002
@@ -43,7 +43,6 @@
 #include <linux/kernel.h>
 #include <linux/genhd.h>
 #include <linux/ps2esdi.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/blk.h>
 #include <linux/blkpg.h>
 #include <linux/mca.h>
@@ -111,7 +110,6 @@
 static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);
 
 static int no_int_yet;
-static int ps2esdi_sizes[MAX_HD << 6];
 static int ps2esdi_drives;
 static struct hd_struct ps2esdi[MAX_HD << 6];
 static u_short io_base;
@@ -156,7 +154,6 @@
 	major_name:	"ed",
 	minor_shift:	6,
 	part:		ps2esdi,
-	sizes:		ps2esdi_sizes,
 	fops:		&ps2esdi_fops,
 };
 
@@ -168,7 +165,7 @@
 
 	/* register the device - pass the name, major number and operations
 	   vector .                                                 */
-	if (devfs_register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
+	if (register_blkdev(MAJOR_NR, "ed", &ps2esdi_fops)) {
 		printk("%s: Unable to get major number %d\n", DEVICE_NAME, MAJOR_NR);
 		return -1;
 	}
@@ -182,7 +179,7 @@
 	if (error) {
 		printk(KERN_WARNING "PS2ESDI: error initialising"
 			" device, releasing resources\n");
-		devfs_unregister_blkdev(MAJOR_NR, "ed");
+		unregister_blkdev(MAJOR_NR, "ed");
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		del_gendisk(&ps2esdi_gendisk);
 		blk_clear(MAJOR_NR);
@@ -233,7 +230,7 @@
 	release_region(io_base, 4);
 	free_dma(dma_arb_level);
 	free_irq(PS2ESDI_IRQ, &ps2esdi_gendisk);
-	devfs_unregister_blkdev(MAJOR_NR, "ed");
+	unregister_blkdev(MAJOR_NR, "ed");
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	del_gendisk(&ps2esdi_gendisk);
 	blk_clear(MAJOR_NR);
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/rd.c	Thu Aug  1 14:17:41 2002
@@ -379,6 +379,7 @@
 		rd_bdev[unit]->bd_openers++;
 		rd_bdev[unit]->bd_block_size = rd_blocksize;
 		rd_bdev[unit]->bd_inode->i_mapping->a_ops = &ramdisk_aops;
+		rd_bdev[unit]->bd_inode->i_size = rd_length[unit];
 		rd_bdev[unit]->bd_queue = &blk_dev[MAJOR_NR].request_queue;
 	}
 
diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c
--- a/drivers/block/swim3.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/block/swim3.c	Thu Aug  1 14:17:40 2002
@@ -1034,7 +1034,7 @@
 
 	if (floppy_count > 0)
 	{
-		if (devfs_register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
+		if (register_blkdev(MAJOR_NR, "fd", &floppy_fops)) {
 			printk(KERN_ERR "Unable to get major %d for floppy\n",
 			       MAJOR_NR);
 			return -EBUSY;
diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c
--- a/drivers/block/umem.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/block/umem.c	Thu Aug  1 14:17:41 2002
@@ -160,7 +160,6 @@
 static struct timer_list battery_timer;
 
 
-static int              mm_sizes[MM_MAXCARDS << MM_SHIFT];
 static struct hd_struct mm_partitions[MM_MAXCARDS << MM_SHIFT];
 
 static int num_cards = 0;
@@ -1206,7 +1205,6 @@
 	printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n");
 
 	memset (cards,    0, MM_MAXCARDS * sizeof(struct cardinfo));
-	memset (mm_sizes, 0, (MM_MAXCARDS << MM_SHIFT) * sizeof (int));
 	memset (mm_partitions, 0,
 		(MM_MAXCARDS << MM_SHIFT) * sizeof(struct hd_struct));
 
@@ -1224,11 +1222,6 @@
 
 	/* Initialize partition size: partion 0 of each card is the entire card */
 	for (i = 0; i < num_cards; i++) {
-		mm_sizes[i << MM_SHIFT] = cards[i].mm_size;
-	}
-        mm_gendisk.sizes = mm_sizes;
-
-	for (i = 0; i < num_cards; i++) {
 		spin_lock_init(&cards[i].lock);
 		mm_partitions[i << MM_SHIFT].nr_sects =
 			cards[i].mm_size * (1024 / MM_HARDSECT);
@@ -1270,8 +1263,6 @@
 	pci_unregister_driver(&mm_pci_driver);
 
 	unregister_blkdev(MAJOR_NR, "umem");
-
-	blk_size     [MAJOR_NR] = NULL;
 
 	/*
 	 * Get our gendisk structure off the list.
diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c
--- a/drivers/block/xd.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/block/xd.c	Thu Aug  1 14:17:39 2002
@@ -122,7 +122,6 @@
 };
 
 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
-static int xd_sizes[XD_MAXDRIVES << 6];
 
 static spinlock_t xd_lock = SPIN_LOCK_UNLOCKED;
 
@@ -133,7 +132,6 @@
 	major_name:	"xd",
 	minor_shift:	6,
 	part:		xd_struct,
-	sizes:		xd_sizes,
 	fops:		&xd_fops,
 };
 
@@ -164,7 +162,7 @@
 	init_timer (&xd_timer); xd_timer.function = xd_wakeup;
 	init_timer (&xd_watchdog_int); xd_watchdog_int.function = xd_watchdog;
 
-	if (devfs_register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
+	if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
 		printk("xd: Unable to get major number %d\n",MAJOR_NR);
 		return -1;
 	}
@@ -1085,7 +1083,7 @@
 	printk(KERN_INFO "XD: Loaded as a module.\n");
 	if (!xd_drives) {
 		/* no drives detected - unload module */
-		devfs_unregister_blkdev(MAJOR_NR, "xd");
+		unregister_blkdev(MAJOR_NR, "xd");
 		xd_done();
 		return (-1);
 	}
@@ -1095,7 +1093,7 @@
 
 void cleanup_module(void)
 {
-	devfs_unregister_blkdev(MAJOR_NR, "xd");
+	unregister_blkdev(MAJOR_NR, "xd");
 	xd_done();
 	devfs_unregister (devfs_handle);
 	if (xd_drives) {
diff -Nru a/drivers/bluetooth/Config.help b/drivers/bluetooth/Config.help
--- a/drivers/bluetooth/Config.help	Thu Aug  1 14:17:40 2002
+++ b/drivers/bluetooth/Config.help	Thu Aug  1 14:17:40 2002
@@ -62,6 +62,20 @@
   Say Y here to compile support for HCI DTL1 devices into the
   kernel or say M to compile it as module (dtl1_cs.o).
 
+HCI BT3C (PC Card) device driver
+CONFIG_BLUEZ_HCIBT3C
+  Bluetooth HCI BT3C (PC Card) driver.
+  This driver provides support for Bluetooth PCMCIA devices with
+  3Com BT3C interface:
+     3Com Bluetooth Card (3CRWB6096)
+     HP Bluetooth Card
+
+  The HCI BT3C driver uses external firmware loader program provided in
+  the BlueFW package. For more information, see <http://bluez.sf.net>.
+
+  Say Y here to compile support for HCI BT3C devices into the
+  kernel or say M to compile it as module (bt3c_cs.o).
+
 HCI BlueCard (PC Card) device driver
 CONFIG_BLUEZ_HCIBLUECARD
   Bluetooth HCI BlueCard (PC Card) driver.
diff -Nru a/drivers/bluetooth/Config.in b/drivers/bluetooth/Config.in
--- a/drivers/bluetooth/Config.in	Thu Aug  1 14:17:40 2002
+++ b/drivers/bluetooth/Config.in	Thu Aug  1 14:17:40 2002
@@ -14,6 +14,8 @@
 
 dep_tristate 'HCI DTL1 (PC Card) driver' CONFIG_BLUEZ_HCIDTL1 $CONFIG_PCMCIA $CONFIG_BLUEZ
 
+dep_tristate 'HCI BT3C (PC Card) driver' CONFIG_BLUEZ_HCIBT3C $CONFIG_PCMCIA $CONFIG_BLUEZ
+
 dep_tristate 'HCI BlueCard (PC Card) driver' CONFIG_BLUEZ_HCIBLUECARD $CONFIG_PCMCIA $CONFIG_BLUEZ
 
 dep_tristate 'HCI VHCI (Virtual HCI device) driver' CONFIG_BLUEZ_HCIVHCI $CONFIG_BLUEZ
diff -Nru a/drivers/bluetooth/Makefile b/drivers/bluetooth/Makefile
--- a/drivers/bluetooth/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/bluetooth/Makefile	Thu Aug  1 14:17:41 2002
@@ -6,6 +6,7 @@
 obj-$(CONFIG_BLUEZ_HCIVHCI)	+= hci_vhci.o
 obj-$(CONFIG_BLUEZ_HCIUART)	+= hci_uart.o
 obj-$(CONFIG_BLUEZ_HCIDTL1)	+= dtl1_cs.o
+obj-$(CONFIG_BLUEZ_HCIBT3C)	+= bt3c_cs.o
 obj-$(CONFIG_BLUEZ_HCIBLUECARD)	+= bluecard_cs.o
 
 hci_uart-y				:= hci_ldisc.o
diff -Nru a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
--- a/drivers/bluetooth/bluecard_cs.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/bluetooth/bluecard_cs.c	Thu Aug  1 14:17:40 2002
@@ -89,16 +89,16 @@
 } bluecard_info_t;
 
 
-void bluecard_config(dev_link_t * link);
+void bluecard_config(dev_link_t *link);
 void bluecard_release(u_long arg);
-int bluecard_event(event_t event, int priority, event_callback_args_t * args);
+int bluecard_event(event_t event, int priority, event_callback_args_t *args);
 
 static dev_info_t dev_info = "bluecard_cs";
 
 dev_link_t *bluecard_attach(void);
 void bluecard_detach(dev_link_t *);
 
-dev_link_t *dev_list = NULL;
+static dev_link_t *dev_list = NULL;
 
 
 /* Default baud rate: 57600, 115200, 230400 or 460800 */
@@ -171,7 +171,7 @@
 
 void bluecard_activity_led_timeout(u_long arg)
 {
-	bluecard_info_t *info = (bluecard_info_t *) arg;
+	bluecard_info_t *info = (bluecard_info_t *)arg;
 	unsigned int iobase = info->link.io.BasePort1;
 
 	if (test_bit(CARD_HAS_ACTIVITY_LED, &(info->hw_state))) {
@@ -184,7 +184,7 @@
 }
 
 
-static void bluecard_enable_activity_led(bluecard_info_t * info)
+static void bluecard_enable_activity_led(bluecard_info_t *info)
 {
 	unsigned int iobase = info->link.io.BasePort1;
 
@@ -208,8 +208,7 @@
 /* ======================== Interrupt handling ======================== */
 
 
-static int bluecard_write(unsigned int iobase, unsigned int offset,
-			  __u8 * buf, int len)
+static int bluecard_write(unsigned int iobase, unsigned int offset, __u8 *buf, int len)
 {
 	int i, actual;
 
@@ -224,7 +223,7 @@
 }
 
 
-static void bluecard_write_wakeup(bluecard_info_t * info)
+static void bluecard_write_wakeup(bluecard_info_t *info)
 {
 	if (!info) {
 		printk(KERN_WARNING "bluecard_cs: Call of write_wakeup for unknown device.\n");
@@ -253,15 +252,13 @@
 			return;
 
 		if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
-			if (!test_bit
-			    (XMIT_BUF_TWO_READY, &(info->tx_state)))
+			if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state)))
 				break;
 			offset = 0x10;
 			command = REG_COMMAND_TX_BUF_TWO;
 			ready_bit = XMIT_BUF_TWO_READY;
 		} else {
-			if (!test_bit
-			    (XMIT_BUF_ONE_READY, &(info->tx_state)))
+			if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state)))
 				break;
 			offset = 0x00;
 			command = REG_COMMAND_TX_BUF_ONE;
@@ -272,11 +269,9 @@
 			break;
 
 		if (skb->pkt_type & 0x80) {
-
 			/* Disable RTS */
 			info->ctrl_reg |= REG_CONTROL_RTS;
 			outb(info->ctrl_reg, iobase + REG_CONTROL);
-
 		}
 
 		/* Activate LED */
@@ -349,8 +344,7 @@
 }
 
 
-static int bluecard_read(unsigned int iobase, unsigned int offset,
-			 __u8 * buf, int size)
+static int bluecard_read(unsigned int iobase, unsigned int offset, __u8 *buf, int size)
 {
 	int i, n, len;
 
@@ -378,7 +372,7 @@
 }
 
 
-static void bluecard_receive(bluecard_info_t * info, unsigned int offset)
+static void bluecard_receive(bluecard_info_t *info, unsigned int offset)
 {
 	unsigned int iobase;
 	unsigned char buf[31];
@@ -410,7 +404,7 @@
 
 		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
 
-			info->rx_skb->dev = (void *) &(info->hdev);
+			info->rx_skb->dev = (void *)&(info->hdev);
 			info->rx_skb->pkt_type = buf[i];
 
 			switch (info->rx_skb->pkt_type) {
@@ -469,20 +463,20 @@
 				switch (info->rx_state) {
 
 				case RECV_WAIT_EVENT_HEADER:
-					eh = (hci_event_hdr *) (info->rx_skb->data);
+					eh = (hci_event_hdr *)(info->rx_skb->data);
 					info->rx_state = RECV_WAIT_DATA;
 					info->rx_count = eh->plen;
 					break;
 
 				case RECV_WAIT_ACL_HEADER:
-					ah = (hci_acl_hdr *) (info->rx_skb->data);
+					ah = (hci_acl_hdr *)(info->rx_skb->data);
 					dlen = __le16_to_cpu(ah->dlen);
 					info->rx_state = RECV_WAIT_DATA;
 					info->rx_count = dlen;
 					break;
 
 				case RECV_WAIT_SCO_HEADER:
-					sh = (hci_sco_hdr *) (info->rx_skb->data);
+					sh = (hci_sco_hdr *)(info->rx_skb->data);
 					info->rx_state = RECV_WAIT_DATA;
 					info->rx_count = sh->dlen;
 					break;
@@ -571,9 +565,8 @@
 
 static int bluecard_hci_set_baud_rate(struct hci_dev *hdev, int baud)
 {
-	bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
 	struct sk_buff *skb;
-	int i;
 
 	/* Ericsson baud rate command */
 	unsigned char cmd[] = { HCI_COMMAND_PKT, 0x09, 0xfc, 0x01, 0x03 };
@@ -604,8 +597,7 @@
 		break;
 	}
 
-	for (i = 0; i < sizeof(cmd); i++)
-		*skb_put(skb, 1) = cmd[i];
+	memcpy(skb_put(skb, sizeof(cmd)), cmd, sizeof(cmd));
 
 	skb_queue_tail(&(info->txq), skb);
 
@@ -621,7 +613,7 @@
 
 static int bluecard_hci_flush(struct hci_dev *hdev)
 {
-	bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
 
 	/* Drop TX queue */
 	skb_queue_purge(&(info->txq));
@@ -632,7 +624,7 @@
 
 static int bluecard_hci_open(struct hci_dev *hdev)
 {
-	bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
 	unsigned int iobase = info->link.io.BasePort1;
 
 	bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@@ -649,7 +641,7 @@
 
 static int bluecard_hci_close(struct hci_dev *hdev)
 {
-	bluecard_info_t *info = (bluecard_info_t *) (hdev->driver_data);
+	bluecard_info_t *info = (bluecard_info_t *)(hdev->driver_data);
 	unsigned int iobase = info->link.io.BasePort1;
 
 	if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
@@ -667,14 +659,14 @@
 static int bluecard_hci_send_frame(struct sk_buff *skb)
 {
 	bluecard_info_t *info;
-	struct hci_dev *hdev = (struct hci_dev *) (skb->dev);
+	struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
 
 	if (!hdev) {
 		printk(KERN_WARNING "bluecard_cs: Frame for unknown HCI device (hdev=NULL).");
 		return -ENODEV;
 	}
 
-	info = (bluecard_info_t *) (hdev->driver_data);
+	info = (bluecard_info_t *)(hdev->driver_data);
 
 	switch (skb->pkt_type) {
 	case HCI_COMMAND_PKT:
@@ -703,8 +695,7 @@
 }
 
 
-static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,
-			      unsigned long arg)
+static int bluecard_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
 {
 	return -ENOIOCTLCMD;
 }
@@ -714,7 +705,7 @@
 /* ======================== Card services HCI interaction ======================== */
 
 
-int bluecard_open(bluecard_info_t * info)
+int bluecard_open(bluecard_info_t *info)
 {
 	unsigned int iobase = info->link.io.BasePort1;
 	struct hci_dev *hdev;
@@ -724,7 +715,7 @@
 
 	init_timer(&(info->timer));
 	info->timer.function = &bluecard_activity_led_timeout;
-	info->timer.data = (u_long) info;
+	info->timer.data = (u_long)info;
 
 	skb_queue_head_init(&(info->txq));
 
@@ -781,7 +772,8 @@
 
 	/* Timeout before it is safe to send the first HCI packet */
 	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout((HZ * 5) / 4);	// or set it to 3/2
+	schedule_timeout((HZ * 5) / 4);		// or set it to 3/2
+
 
 	/* Initialize and register HCI device */
 
@@ -806,7 +798,7 @@
 }
 
 
-int bluecard_close(bluecard_info_t * info)
+int bluecard_close(bluecard_info_t *info)
 {
 	unsigned int iobase = info->link.io.BasePort1;
 	struct hci_dev *hdev = &(info->hdev);
@@ -858,7 +850,7 @@
 	link->priv = info;
 
 	link->release.function = &bluecard_release;
-	link->release.data = (u_long) link;
+	link->release.data = (u_long)link;
 	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 	link->io.NumPorts1 = 8;
 	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
@@ -883,9 +875,9 @@
 	client_reg.dev_info = &dev_info;
 	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
 	client_reg.EventMask =
-	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+		CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+		CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+		CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
 	client_reg.event_handler = &bluecard_event;
 	client_reg.Version = 0x0210;
 	client_reg.event_callback_args.client_data = link;
@@ -901,7 +893,7 @@
 }
 
 
-void bluecard_detach(dev_link_t * link)
+void bluecard_detach(dev_link_t *link)
 {
 	bluecard_info_t *info = link->priv;
 	dev_link_t **linkp;
@@ -917,7 +909,7 @@
 
 	del_timer(&link->release);
 	if (link->state & DEV_CONFIG)
-		bluecard_release((u_long) link);
+		bluecard_release((u_long)link);
 
 	if (link->handle) {
 		ret = CardServices(DeregisterClient, link->handle);
@@ -932,8 +924,7 @@
 }
 
 
-static int get_tuple(int fn, client_handle_t handle, tuple_t * tuple,
-		     cisparse_t * parse)
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
 {
 	int i;
 
@@ -952,7 +943,7 @@
 #define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
 #define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
 
-void bluecard_config(dev_link_t * link)
+void bluecard_config(dev_link_t *link)
 {
 	client_handle_t handle = link->handle;
 	bluecard_info_t *info = link->priv;
@@ -962,7 +953,7 @@
 	config_info_t config;
 	int i, n, last_ret, last_fn;
 
-	tuple.TupleData = (cisdata_t *) buf;
+	tuple.TupleData = (cisdata_t *)buf;
 	tuple.TupleOffset = 0;
 	tuple.TupleDataMax = 255;
 	tuple.Attributes = 0;
@@ -1010,12 +1001,12 @@
 		goto failed;
 	}
 
-
 	MOD_INC_USE_COUNT;
 
 	if (bluecard_open(info) != 0)
 		goto failed;
 
+	strcpy(info->node.dev_name, info->hdev.name);
 	link->dev = &info->node;
 	link->state &= ~DEV_CONFIG_PENDING;
 
@@ -1025,13 +1016,13 @@
 	cs_error(link->handle, last_fn, last_ret);
 
 failed:
-	bluecard_release((u_long) link);
+	bluecard_release((u_long)link);
 }
 
 
 void bluecard_release(u_long arg)
 {
-	dev_link_t *link = (dev_link_t *) arg;
+	dev_link_t *link = (dev_link_t *)arg;
 	bluecard_info_t *info = link->priv;
 
 	if (link->state & DEV_PRESENT)
@@ -1049,8 +1040,7 @@
 }
 
 
-int bluecard_event(event_t event, int priority,
-		   event_callback_args_t * args)
+int bluecard_event(event_t event, int priority, event_callback_args_t *args)
 {
 	dev_link_t *link = args->client_data;
 	bluecard_info_t *info = link->priv;
@@ -1079,8 +1069,7 @@
 		/* Fall through... */
 	case CS_EVENT_CARD_RESET:
 		if (DEV_OK(link))
-			CardServices(RequestConfiguration, link->handle,
-				     &link->conf);
+			CardServices(RequestConfiguration, link->handle, &link->conf);
 		break;
 	}
 
diff -Nru a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/bluetooth/bt3c_cs.c	Thu Aug  1 14:17:41 2002
@@ -0,0 +1,944 @@
+/*
+ *
+ *  Driver for the 3Com Bluetooth PCMCIA card
+ *
+ *  Copyright (C) 2001-2002  Marcel Holtmann <marcel@holtmann.org>
+ *                           Jose Orlando Pereira <jop@di.uminho.pt>
+ *
+ *
+ *  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;
+ *
+ *  Software distributed under the License is distributed on an "AS
+ *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ *  implied. See the License for the specific language governing
+ *  rights and limitations under the License.
+ *
+ *  The initial developer of the original code is David A. Hinds
+ *  <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
+ *  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+
+#define __KERNEL_SYSCALLS__
+
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/spinlock.h>
+
+#include <linux/skbuff.h>
+#include <linux/string.h>
+#include <linux/serial.h>
+#include <linux/serial_reg.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ciscode.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+
+
+
+/* ======================== Module parameters ======================== */
+
+
+/* Bit map of interrupts to choose from */
+static u_int irq_mask = 0xffff;
+static int irq_list[4] = { -1 };
+
+MODULE_PARM(irq_mask, "i");
+MODULE_PARM(irq_list, "1-4i");
+
+MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>, Jose Orlando Pereira <jop@di.uminho.pt>");
+MODULE_DESCRIPTION("BlueZ driver for the 3Com Bluetooth PCMCIA card");
+MODULE_LICENSE("GPL");
+
+
+
+/* ======================== Local structures ======================== */
+
+
+typedef struct bt3c_info_t {
+	dev_link_t link;
+	dev_node_t node;
+
+	struct hci_dev hdev;
+
+	spinlock_t lock;		/* For serializing operations */
+
+	struct sk_buff_head txq;
+	unsigned long tx_state;
+
+	unsigned long rx_state;
+	unsigned long rx_count;
+	struct sk_buff *rx_skb;
+} bt3c_info_t;
+
+
+void bt3c_config(dev_link_t *link);
+void bt3c_release(u_long arg);
+int bt3c_event(event_t event, int priority, event_callback_args_t *args);
+
+static dev_info_t dev_info = "bt3c_cs";
+
+dev_link_t *bt3c_attach(void);
+void bt3c_detach(dev_link_t *);
+
+static dev_link_t *dev_list = NULL;
+
+
+/* Transmit states  */
+#define XMIT_SENDING  1
+#define XMIT_WAKEUP   2
+#define XMIT_WAITING  8
+
+/* Receiver states */
+#define RECV_WAIT_PACKET_TYPE   0
+#define RECV_WAIT_EVENT_HEADER  1
+#define RECV_WAIT_ACL_HEADER    2
+#define RECV_WAIT_SCO_HEADER    3
+#define RECV_WAIT_DATA          4
+
+
+
+/* ======================== Special I/O functions ======================== */
+
+
+#define DATA_L   0
+#define DATA_H   1
+#define ADDR_L   2
+#define ADDR_H   3
+#define CONTROL  4
+
+
+inline void bt3c_address(unsigned int iobase, unsigned short addr)
+{
+	outb(addr & 0xff, iobase + ADDR_L);
+	outb((addr >> 8) & 0xff, iobase + ADDR_H);
+}
+
+
+inline void bt3c_put(unsigned int iobase, unsigned short value)
+{
+	outb(value & 0xff, iobase + DATA_L);
+	outb((value >> 8) & 0xff, iobase + DATA_H);
+}
+
+
+inline void bt3c_io_write(unsigned int iobase, unsigned short addr, unsigned short value)
+{
+	bt3c_address(iobase, addr);
+	bt3c_put(iobase, value);
+}
+
+
+inline unsigned short bt3c_get(unsigned int iobase)
+{
+	unsigned short value = inb(iobase + DATA_L);
+
+	value |= inb(iobase + DATA_H) << 8;
+
+	return value;
+}
+
+
+inline unsigned short bt3c_read(unsigned int iobase, unsigned short addr)
+{
+	bt3c_address(iobase, addr);
+
+	return bt3c_get(iobase);
+}
+
+
+
+/* ======================== Interrupt handling ======================== */
+
+
+static int bt3c_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
+{
+	int actual = 0;
+
+	bt3c_address(iobase, 0x7080);
+
+	/* Fill FIFO with current frame */
+	while (actual < len) {
+		/* Transmit next byte */
+		bt3c_put(iobase, buf[actual]);
+		actual++;
+	}
+
+	bt3c_io_write(iobase, 0x7005, actual);
+
+	return actual;
+}
+
+
+static void bt3c_write_wakeup(bt3c_info_t *info, int from)
+{
+	unsigned long flags;
+
+	if (!info) {
+		printk(KERN_WARNING "bt3c_cs: Call of write_wakeup for unknown device.\n");
+		return;
+	}
+
+	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state)))
+		return;
+
+	spin_lock_irqsave(&(info->lock), flags);
+
+	do {
+		register unsigned int iobase = info->link.io.BasePort1;
+		register struct sk_buff *skb;
+		register int len;
+
+		if (!(info->link.state & DEV_PRESENT))
+			break;
+
+
+		if (!(skb = skb_dequeue(&(info->txq)))) {
+			clear_bit(XMIT_SENDING, &(info->tx_state));
+			break;
+		}
+
+		/* Send frame */
+		len = bt3c_write(iobase, 256, skb->data, skb->len);
+
+		if (len != skb->len) {
+			printk(KERN_WARNING "bt3c_cs: very strange\n");
+		}
+
+		kfree_skb(skb);
+
+		info->hdev.stat.byte_tx += len;
+
+	} while (0);
+
+	spin_unlock_irqrestore(&(info->lock), flags);
+}
+
+
+static void bt3c_receive(bt3c_info_t *info)
+{
+	unsigned int iobase;
+	int size = 0, avail;
+
+	if (!info) {
+		printk(KERN_WARNING "bt3c_cs: Call of receive for unknown device.\n");
+		return;
+	}
+
+	iobase = info->link.io.BasePort1;
+
+	avail = bt3c_read(iobase, 0x7006);
+	//printk("bt3c_cs: receiving %d bytes\n", avail);
+
+	bt3c_address(iobase, 0x7480);
+	while (size < avail) {
+		size++;
+		info->hdev.stat.byte_rx++;
+
+		/* Allocate packet */
+		if (info->rx_skb == NULL) {
+			info->rx_state = RECV_WAIT_PACKET_TYPE;
+			info->rx_count = 0;
+			if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
+				printk(KERN_WARNING "bt3c_cs: Can't allocate mem for new packet.\n");
+				return;
+			}
+		}
+
+
+		if (info->rx_state == RECV_WAIT_PACKET_TYPE) {
+
+			info->rx_skb->dev = (void *)&(info->hdev);
+			info->rx_skb->pkt_type = inb(iobase + DATA_L);
+			inb(iobase + DATA_H);
+			//printk("bt3c: PACKET_TYPE=%02x\n", info->rx_skb->pkt_type);
+
+			switch (info->rx_skb->pkt_type) {
+
+			case HCI_EVENT_PKT:
+				info->rx_state = RECV_WAIT_EVENT_HEADER;
+				info->rx_count = HCI_EVENT_HDR_SIZE;
+				break;
+
+			case HCI_ACLDATA_PKT:
+				info->rx_state = RECV_WAIT_ACL_HEADER;
+				info->rx_count = HCI_ACL_HDR_SIZE;
+				break;
+
+			case HCI_SCODATA_PKT:
+				info->rx_state = RECV_WAIT_SCO_HEADER;
+				info->rx_count = HCI_SCO_HDR_SIZE;
+				break;
+
+			default:
+				/* Unknown packet */
+				printk(KERN_WARNING "bt3c_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+				info->hdev.stat.err_rx++;
+				clear_bit(HCI_RUNNING, &(info->hdev.flags));
+
+				kfree_skb(info->rx_skb);
+				info->rx_skb = NULL;
+				break;
+
+			}
+
+		} else {
+
+			__u8 x = inb(iobase + DATA_L);
+
+			*skb_put(info->rx_skb, 1) = x;
+			inb(iobase + DATA_H);
+			info->rx_count--;
+
+			if (info->rx_count == 0) {
+
+				int dlen;
+				hci_event_hdr *eh;
+				hci_acl_hdr *ah;
+				hci_sco_hdr *sh;
+
+				switch (info->rx_state) {
+
+				case RECV_WAIT_EVENT_HEADER:
+					eh = (hci_event_hdr *)(info->rx_skb->data);
+					info->rx_state = RECV_WAIT_DATA;
+					info->rx_count = eh->plen;
+					break;
+
+				case RECV_WAIT_ACL_HEADER:
+					ah = (hci_acl_hdr *)(info->rx_skb->data);
+					dlen = __le16_to_cpu(ah->dlen);
+					info->rx_state = RECV_WAIT_DATA;
+					info->rx_count = dlen;
+					break;
+
+				case RECV_WAIT_SCO_HEADER:
+					sh = (hci_sco_hdr *)(info->rx_skb->data);
+					info->rx_state = RECV_WAIT_DATA;
+					info->rx_count = sh->dlen;
+					break;
+
+				case RECV_WAIT_DATA:
+					hci_recv_frame(info->rx_skb);
+					info->rx_skb = NULL;
+					break;
+
+				}
+
+			}
+
+		}
+
+	}
+
+	bt3c_io_write(iobase, 0x7006, 0x0000);
+}
+
+
+void bt3c_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+{
+	bt3c_info_t *info = dev_inst;
+	unsigned int iobase;
+	int iir;
+
+	if (!info) {
+		printk(KERN_WARNING "bt3c_cs: Call of irq %d for unknown device.\n", irq);
+		return;
+	}
+
+	iobase = info->link.io.BasePort1;
+
+	spin_lock(&(info->lock));
+
+	iir = inb(iobase + CONTROL);
+	if (iir & 0x80) {
+		int stat = bt3c_read(iobase, 0x7001);
+
+		if ((stat & 0xff) == 0x7f) {
+			printk(KERN_WARNING "bt3c_cs: STRANGE stat=%04x\n", stat);
+		} else if ((stat & 0xff) != 0xff) {
+			if (stat & 0x0020) {
+				int stat = bt3c_read(iobase, 0x7002) & 0x10;
+				printk(KERN_WARNING "bt3c_cs: antena %s\n", stat ? "OUT" : "IN");
+			}
+			if (stat & 0x0001)
+				bt3c_receive(info);
+			if (stat & 0x0002) {
+				//printk("bt3c_cs: ACK %04x\n", stat);
+				clear_bit(XMIT_SENDING, &(info->tx_state));
+				bt3c_write_wakeup(info, 1);
+			}
+
+			bt3c_io_write(iobase, 0x7001, 0x0000);
+
+			outb(iir, iobase + CONTROL);
+		}
+	}
+
+	spin_unlock(&(info->lock));
+}
+
+
+
+
+/* ======================== HCI interface ======================== */
+
+
+static int bt3c_hci_flush(struct hci_dev *hdev)
+{
+	bt3c_info_t *info = (bt3c_info_t *)(hdev->driver_data);
+
+	/* Drop TX queue */
+	skb_queue_purge(&(info->txq));
+
+	return 0;
+}
+
+
+static int bt3c_hci_open(struct hci_dev *hdev)
+{
+	set_bit(HCI_RUNNING, &(hdev->flags));
+
+	return 0;
+}
+
+
+static int bt3c_hci_close(struct hci_dev *hdev)
+{
+	if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
+		return 0;
+
+	bt3c_hci_flush(hdev);
+
+	return 0;
+}
+
+
+static int bt3c_hci_send_frame(struct sk_buff *skb)
+{
+	bt3c_info_t *info;
+	struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
+
+	if (!hdev) {
+		printk(KERN_WARNING "bt3c_cs: Frame for unknown HCI device (hdev=NULL).");
+		return -ENODEV;
+	}
+
+	info = (bt3c_info_t *) (hdev->driver_data);
+
+	switch (skb->pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+	};
+
+	/* Prepend skb with frame type */
+	memcpy(skb_push(skb, 1), &(skb->pkt_type), 1);
+	skb_queue_tail(&(info->txq), skb);
+
+	bt3c_write_wakeup(info, 0);
+
+	return 0;
+}
+
+
+static void bt3c_hci_destruct(struct hci_dev *hdev)
+{
+}
+
+
+static int bt3c_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg)
+{
+	return -ENOIOCTLCMD;
+}
+
+
+
+/* ======================== User mode firmware loader ======================== */
+
+
+#define FW_LOADER  "/sbin/bluefw"
+static int errno;
+
+
+static int bt3c_fw_loader_exec(void *dev)
+{
+	char *argv[] = { FW_LOADER, "pccard", dev, NULL };
+	char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+	int err;
+
+	err = exec_usermodehelper(FW_LOADER, argv, envp);
+	if (err)
+		printk(KERN_WARNING "bt3c_cs: Failed to exec \"%s pccard %s\".\n", FW_LOADER, (char *)dev);
+
+	return err;
+}
+
+
+static int bt3c_firmware_load(bt3c_info_t *info)
+{
+	sigset_t tmpsig;
+	char dev[16];
+	pid_t pid;
+	int result;
+
+	/* Check if root fs is mounted */
+	if (!current->fs->root) {
+		printk(KERN_WARNING "bt3c_cs: Root filesystem is not mounted.\n");
+		return -EPERM;
+	}
+
+	sprintf(dev, "%04x", info->link.io.BasePort1);
+
+	pid = kernel_thread(bt3c_fw_loader_exec, (void *)dev, 0);
+	if (pid < 0) {
+		printk(KERN_WARNING "bt3c_cs: Forking of kernel thread failed (errno=%d).\n", -pid);
+		return pid;
+	}
+
+	/* Block signals, everything but SIGKILL/SIGSTOP */
+	spin_lock_irq(&current->sigmask_lock);
+	tmpsig = current->blocked;
+	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
+	recalc_sigpending();
+	spin_unlock_irq(&current->sigmask_lock);
+
+	result = waitpid(pid, NULL, __WCLONE);
+
+	/* Allow signals again */
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = tmpsig;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sigmask_lock);
+
+	if (result != pid) {
+		printk(KERN_WARNING "bt3c_cs: Waiting for pid %d failed (errno=%d).\n", pid, -result);
+		return -result;
+	}
+
+	return 0;
+}
+
+
+
+/* ======================== Card services HCI interaction ======================== */
+
+
+int bt3c_open(bt3c_info_t *info)
+{
+	struct hci_dev *hdev;
+	int err;
+
+	spin_lock_init(&(info->lock));
+
+	skb_queue_head_init(&(info->txq));
+
+	info->rx_state = RECV_WAIT_PACKET_TYPE;
+	info->rx_count = 0;
+	info->rx_skb = NULL;
+
+	/* Load firmware */
+
+	if ((err = bt3c_firmware_load(info)) < 0)
+		return err;
+
+	/* Timeout before it is safe to send the first HCI packet */
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ);
+
+
+	/* Initialize and register HCI device */
+
+	hdev = &(info->hdev);
+
+	hdev->type = HCI_PCCARD;
+	hdev->driver_data = info;
+
+	hdev->open = bt3c_hci_open;
+	hdev->close = bt3c_hci_close;
+	hdev->flush = bt3c_hci_flush;
+	hdev->send = bt3c_hci_send_frame;
+	hdev->destruct = bt3c_hci_destruct;
+	hdev->ioctl = bt3c_hci_ioctl;
+
+	if (hci_register_dev(hdev) < 0) {
+		printk(KERN_WARNING "bt3c_cs: Can't register HCI device %s.\n", hdev->name);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+
+int bt3c_close(bt3c_info_t *info)
+{
+	struct hci_dev *hdev = &(info->hdev);
+
+	bt3c_hci_close(hdev);
+
+	if (hci_unregister_dev(hdev) < 0)
+		printk(KERN_WARNING "bt3c_cs: Can't unregister HCI device %s.\n", hdev->name);
+
+	return 0;
+}
+
+
+
+/* ======================== Card services ======================== */
+
+
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+	error_info_t err = { func, ret };
+
+	CardServices(ReportError, handle, &err);
+}
+
+
+dev_link_t *bt3c_attach(void)
+{
+	bt3c_info_t *info;
+	client_reg_t client_reg;
+	dev_link_t *link;
+	int i, ret;
+
+	/* Create new info device */
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return NULL;
+	memset(info, 0, sizeof(*info));
+
+	link = &info->link;
+	link->priv = info;
+
+	link->release.function = &bt3c_release;
+	link->release.data = (u_long)link;
+	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+	link->io.NumPorts1 = 8;
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+	link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+
+	if (irq_list[0] == -1)
+		link->irq.IRQInfo2 = irq_mask;
+	else
+		for (i = 0; i < 4; i++)
+			link->irq.IRQInfo2 |= 1 << irq_list[i];
+
+	link->irq.Handler = bt3c_interrupt;
+	link->irq.Instance = info;
+
+	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->conf.Vcc = 50;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+
+	/* Register with Card Services */
+	link->next = dev_list;
+	dev_list = link;
+	client_reg.dev_info = &dev_info;
+	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+	client_reg.EventMask =
+	    CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+	    CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+	    CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+	client_reg.event_handler = &bt3c_event;
+	client_reg.Version = 0x0210;
+	client_reg.event_callback_args.client_data = link;
+
+	ret = CardServices(RegisterClient, &link->handle, &client_reg);
+	if (ret != CS_SUCCESS) {
+		cs_error(link->handle, RegisterClient, ret);
+		bt3c_detach(link);
+		return NULL;
+	}
+
+	return link;
+}
+
+
+void bt3c_detach(dev_link_t *link)
+{
+	bt3c_info_t *info = link->priv;
+	dev_link_t **linkp;
+	int ret;
+
+	/* Locate device structure */
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link)
+			break;
+
+	if (*linkp == NULL)
+		return;
+
+	del_timer(&link->release);
+
+	if (link->state & DEV_CONFIG)
+		bt3c_release((u_long)link);
+
+	if (link->handle) {
+		ret = CardServices(DeregisterClient, link->handle);
+		if (ret != CS_SUCCESS)
+			cs_error(link->handle, DeregisterClient, ret);
+	}
+
+	/* Unlink device structure, free bits */
+	*linkp = link->next;
+
+	kfree(info);
+}
+
+
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+{
+	int i;
+
+	i = CardServices(fn, handle, tuple);
+	if (i != CS_SUCCESS)
+		return CS_NO_MORE_ITEMS;
+
+	i = CardServices(GetTupleData, handle, tuple);
+	if (i != CS_SUCCESS)
+		return i;
+
+	return CardServices(ParseTuple, handle, tuple, parse);
+}
+
+
+#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
+#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
+
+void bt3c_config(dev_link_t *link)
+{
+	static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+	client_handle_t handle = link->handle;
+	bt3c_info_t *info = link->priv;
+	tuple_t tuple;
+	u_short buf[256];
+	cisparse_t parse;
+	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+	config_info_t config;
+	int i, j, try, last_ret, last_fn;
+
+	tuple.TupleData = (cisdata_t *)buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 255;
+	tuple.Attributes = 0;
+
+	/* Get configuration register information */
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	last_ret = first_tuple(handle, &tuple, &parse);
+	if (last_ret != CS_SUCCESS) {
+		last_fn = ParseTuple;
+		goto cs_failed;
+	}
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+
+	/* Configure card */
+	link->state |= DEV_CONFIG;
+	i = CardServices(GetConfigurationInfo, handle, &config);
+	link->conf.Vcc = config.Vcc;
+
+	/* First pass: look for a config entry that looks normal. */
+	tuple.TupleData = (cisdata_t *)buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 255;
+	tuple.Attributes = 0;
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+	/* Two tries: without IO aliases, then with aliases */
+	for (try = 0; try < 2; try++) {
+		i = first_tuple(handle, &tuple, &parse);
+		while (i != CS_NO_MORE_ITEMS) {
+			if (i != CS_SUCCESS)
+				goto next_entry;
+			if (cf->vpp1.present & (1 << CISTPL_POWER_VNOM))
+				link->conf.Vpp1 = link->conf.Vpp2 = cf->vpp1.param[CISTPL_POWER_VNOM] / 10000;
+			if ((cf->io.nwin > 0) && (cf->io.win[0].len == 8) && (cf->io.win[0].base != 0)) {
+				link->conf.ConfigIndex = cf->index;
+				link->io.BasePort1 = cf->io.win[0].base;
+				link->io.IOAddrLines = (try == 0) ? 16 : cf->io.flags & CISTPL_IO_LINES_MASK;
+				i = CardServices(RequestIO, link->handle, &link->io);
+				if (i == CS_SUCCESS)
+					goto found_port;
+			}
+next_entry:
+			i = next_tuple(handle, &tuple, &parse);
+		}
+	}
+
+	/* Second pass: try to find an entry that isn't picky about
+	   its base address, then try to grab any standard serial port
+	   address, and finally try to get any free port. */
+	i = first_tuple(handle, &tuple, &parse);
+	while (i != CS_NO_MORE_ITEMS) {
+		if ((i == CS_SUCCESS) && (cf->io.nwin > 0) && ((cf->io.flags & CISTPL_IO_LINES_MASK) <= 3)) {
+			link->conf.ConfigIndex = cf->index;
+			for (j = 0; j < 5; j++) {
+				link->io.BasePort1 = base[j];
+				link->io.IOAddrLines = base[j] ? 16 : 3;
+				i = CardServices(RequestIO, link->handle, &link->io);
+				if (i == CS_SUCCESS)
+					goto found_port;
+			}
+		}
+		i = next_tuple(handle, &tuple, &parse);
+	}
+
+found_port:
+	if (i != CS_SUCCESS) {
+		printk(KERN_NOTICE "bt3c_cs: No usable port range found. Giving up.\n");
+		cs_error(link->handle, RequestIO, i);
+		goto failed;
+	}
+
+	i = CardServices(RequestIRQ, link->handle, &link->irq);
+	if (i != CS_SUCCESS) {
+		cs_error(link->handle, RequestIRQ, i);
+		link->irq.AssignedIRQ = 0;
+	}
+
+	i = CardServices(RequestConfiguration, link->handle, &link->conf);
+	if (i != CS_SUCCESS) {
+		cs_error(link->handle, RequestConfiguration, i);
+		goto failed;
+	}
+
+	MOD_INC_USE_COUNT;
+
+	if (bt3c_open(info) != 0)
+		goto failed;
+
+	strcpy(info->node.dev_name, info->hdev.name);
+	link->dev = &info->node;
+	link->state &= ~DEV_CONFIG_PENDING;
+
+	return;
+
+cs_failed:
+	cs_error(link->handle, last_fn, last_ret);
+
+failed:
+	bt3c_release((u_long)link);
+}
+
+
+void bt3c_release(u_long arg)
+{
+	dev_link_t *link = (dev_link_t *)arg;
+	bt3c_info_t *info = link->priv;
+
+	if (link->state & DEV_PRESENT)
+		bt3c_close(info);
+
+	MOD_DEC_USE_COUNT;
+
+	link->dev = NULL;
+
+	CardServices(ReleaseConfiguration, link->handle);
+	CardServices(ReleaseIO, link->handle, &link->io);
+	CardServices(ReleaseIRQ, link->handle, &link->irq);
+
+	link->state &= ~DEV_CONFIG;
+}
+
+
+int bt3c_event(event_t event, int priority, event_callback_args_t *args)
+{
+	dev_link_t *link = args->client_data;
+	bt3c_info_t *info = link->priv;
+
+	switch (event) {
+	case CS_EVENT_CARD_REMOVAL:
+		link->state &= ~DEV_PRESENT;
+		if (link->state & DEV_CONFIG) {
+			bt3c_close(info);
+			mod_timer(&link->release, jiffies + HZ / 20);
+		}
+		break;
+	case CS_EVENT_CARD_INSERTION:
+		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+		bt3c_config(link);
+		break;
+	case CS_EVENT_PM_SUSPEND:
+		link->state |= DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+		if (link->state & DEV_CONFIG)
+			CardServices(ReleaseConfiguration, link->handle);
+		break;
+	case CS_EVENT_PM_RESUME:
+		link->state &= ~DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_CARD_RESET:
+		if (DEV_OK(link))
+			CardServices(RequestConfiguration, link->handle, &link->conf);
+		break;
+	}
+
+	return 0;
+}
+
+
+
+/* ======================== Module initialization ======================== */
+
+
+int __init init_bt3c_cs(void)
+{
+	servinfo_t serv;
+	int err;
+
+	CardServices(GetCardServicesInfo, &serv);
+	if (serv.Revision != CS_RELEASE_CODE) {
+		printk(KERN_NOTICE "bt3c_cs: Card Services release does not match!\n");
+		return -1;
+	}
+
+	err = register_pccard_driver(&dev_info, &bt3c_attach, &bt3c_detach);
+
+	return err;
+}
+
+
+void __exit exit_bt3c_cs(void)
+{
+	unregister_pccard_driver(&dev_info);
+
+	while (dev_list != NULL)
+		bt3c_detach(dev_list);
+}
+
+
+module_init(init_bt3c_cs);
+module_exit(exit_bt3c_cs);
diff -Nru a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c
--- a/drivers/bluetooth/dtl1_cs.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/bluetooth/dtl1_cs.c	Thu Aug  1 14:17:40 2002
@@ -75,23 +75,22 @@
 
 
 typedef struct dtl1_info_t {
-  dev_link_t link;
-  dev_node_t node;
+	dev_link_t link;
+	dev_node_t node;
 
-  struct hci_dev hdev;
+	struct hci_dev hdev;
 
-  spinlock_t lock;          /* For serializing operations */
+	spinlock_t lock;		/* For serializing operations */
 
-  unsigned long flowmask;   /* HCI flow mask */
-  int ri_latch;
+	unsigned long flowmask;		/* HCI flow mask */
+	int ri_latch;
 
-  struct sk_buff_head txq;
-  unsigned long tx_state;
-
-  unsigned long rx_state;
-  unsigned long rx_count;
-  struct sk_buff *rx_skb;
+	struct sk_buff_head txq;
+	unsigned long tx_state;
 
+	unsigned long rx_state;
+	unsigned long rx_count;
+	struct sk_buff *rx_skb;
 } dtl1_info_t;
 
 
@@ -104,7 +103,7 @@
 dev_link_t *dtl1_attach(void);
 void dtl1_detach(dev_link_t *);
 
-dev_link_t *dev_list = NULL;
+static dev_link_t *dev_list = NULL;
 
 
 /* Transmit states  */
@@ -118,282 +117,253 @@
 
 
 typedef struct {
-  u8 type;
-  u8 zero;
-  u16 len;
-} __attribute__ ((packed)) nsh_t;   /* Nokia Specific Header */
+	u8 type;
+	u8 zero;
+	u16 len;
+} __attribute__ ((packed)) nsh_t;	/* Nokia Specific Header */
 
-#define NSHL  4    /* Nokia Specific Header Length */
+#define NSHL  4				/* Nokia Specific Header Length */
 
 
 
 /* ======================== Interrupt handling ======================== */
 
 
-static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len) {
-
-  int actual = 0;
-
-
-  /* Tx FIFO should be empty */
-  if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
-    return 0;
-
-
-  /* Fill FIFO with current frame */
-  while ((fifo_size-- > 0) && (actual < len)) {
-    /* Transmit next byte */
-    outb(buf[actual], iobase + UART_TX);
-    actual++;
-  }
-
-
-  return actual;
-
-}
-
-
-static void dtl1_write_wakeup(dtl1_info_t *info) {
-
-  if (!info) {
-    printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n");
-    return;
-  }
-
-
-  if (test_bit(XMIT_WAITING, &(info->tx_state))) {
-    set_bit(XMIT_WAKEUP, &(info->tx_state));
-    return;
-  }
-
-  if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
-    set_bit(XMIT_WAKEUP, &(info->tx_state));
-    return;
-  }
-
-
-  do {
-    register unsigned int iobase = info->link.io.BasePort1;
-    register struct sk_buff *skb;
-    register int len;
-
-    clear_bit(XMIT_WAKEUP, &(info->tx_state));
-
-    if (!(info->link.state & DEV_PRESENT))
-      return;
-
-
-    if (!(skb = skb_dequeue(&(info->txq))))
-      break;
-
-
-    /* Send frame */
-    len = dtl1_write(iobase, 32, skb->data, skb->len);
-
-    if (len == skb->len) {
-      set_bit(XMIT_WAITING, &(info->tx_state));
-      kfree_skb(skb);
-    }
-    else {
-      skb_pull(skb, len);
-      skb_queue_head(&(info->txq), skb);
-    }
-
-    info->hdev.stat.byte_tx += len;
-
-  } while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
-
-
-  clear_bit(XMIT_SENDING, &(info->tx_state));
-
-}
-
-
-static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb) {
-
-  u8 flowmask = *(u8 *)skb->data;
-  int i;
-
-
-  printk(KERN_INFO "dtl1_cs: Nokia control data = ");
-  for (i = 0; i < skb->len; i++) {
-    printk("%02x ", skb->data[i]);
-  }
-  printk("\n");
-
-
-  /* transition to active state */
-  if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
-    clear_bit(XMIT_WAITING, &(info->tx_state));
-    dtl1_write_wakeup(info);
-  }
-
-  info->flowmask = flowmask;
-
-
-  kfree_skb(skb);
-
-}
-
-
-static void dtl1_receive(dtl1_info_t *info) {
-
-  unsigned int iobase;
-  nsh_t *nsh;
-  int boguscount = 0;
-
-
-  if (!info) {
-    printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n");
-    return;
-  }
-
-
-  iobase = info->link.io.BasePort1;
-
-  do {
-    info->hdev.stat.byte_rx++;
-
-    /* Allocate packet */
-    if (info->rx_skb == NULL)
-      if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
-        printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n");
-        info->rx_state = RECV_WAIT_NSH;
-        info->rx_count = NSHL;
-        return;
-    }
-
-
-    *skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
-    nsh = (nsh_t *)info->rx_skb->data;
-
-    info->rx_count--;
-
-
-    if (info->rx_count == 0) {
-
-      switch (info->rx_state) {
-      case RECV_WAIT_NSH:
-        info->rx_state = RECV_WAIT_DATA;
-        info->rx_count = nsh->len + (nsh->len & 0x0001);
-        break;
-      case RECV_WAIT_DATA:
-        info->rx_skb->pkt_type = nsh->type;
-
-        /* remove PAD byte if it exists */
-        if (nsh->len & 0x0001) {
-          info->rx_skb->tail--;
-          info->rx_skb->len--;
-        }
-
-        /* remove NSH */
-        skb_pull(info->rx_skb, NSHL);
-
-
-        switch (info->rx_skb->pkt_type) {
-        case 0x80:
-          /* control data for the Nokia Card */
-          dtl1_control(info, info->rx_skb);
-          break;
-        case 0x82:
-        case 0x83:
-        case 0x84:
-          /* send frame to the HCI layer */
-          info->rx_skb->dev = (void *)&(info->hdev);
-          info->rx_skb->pkt_type &= 0x0f;
-          hci_recv_frame(info->rx_skb);
-          break;
-        default:
-          /* unknown packet */
-          printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
-          kfree_skb(info->rx_skb);
-          break;
-        }
-
-
-        info->rx_state = RECV_WAIT_NSH;
-        info->rx_count = NSHL;
-        info->rx_skb = NULL;
-        break;
-      }
-
-    }
-
-
-    /* Make sure we don't stay here to long */
-    if (boguscount++ > 32)
-      break;
-
-  } while (inb(iobase + UART_LSR) & UART_LSR_DR);
-
-
-}
-
-
-void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs) {
-
-  dtl1_info_t *info = dev_inst;
-  unsigned int iobase;
-  unsigned char msr;
-  int boguscount = 0;
-  int iir, lsr;
-
-
-  if (!info) {
-    printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq);
-    return;
-  }
-
-
-  iobase = info->link.io.BasePort1;
-
-
-  spin_lock(&(info->lock));
-
-  iir = inb(iobase + UART_IIR) & UART_IIR_ID;
-  while (iir) {
-
-    /* Clear interrupt */
-    lsr = inb(iobase + UART_LSR);
-
-    switch (iir) {
-    case UART_IIR_RLSI:
-      printk(KERN_NOTICE "dtl1_cs: RLSI\n");
-      break;
-    case UART_IIR_RDI:
-      /* Receive interrupt */
-      dtl1_receive(info);
-      break;
-    case UART_IIR_THRI:
-      if (lsr & UART_LSR_THRE) {
-        /* Transmitter ready for data */
-        dtl1_write_wakeup(info);
-      }
-      break;
-    default:
-      printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir);
-      break;
-    }
-
-    /* Make sure we don't stay here to long */
-    if (boguscount++ > 100)
-      break;
-
-    iir = inb(iobase + UART_IIR) & UART_IIR_ID;
-
-  }
-
-
-  msr = inb(iobase + UART_MSR);
-
-  if (info->ri_latch ^ (msr & UART_MSR_RI)) {
-    info->ri_latch = msr & UART_MSR_RI;
-    clear_bit(XMIT_WAITING, &(info->tx_state));
-    dtl1_write_wakeup(info);
-  }
-
-  spin_unlock(&(info->lock));
+static int dtl1_write(unsigned int iobase, int fifo_size, __u8 *buf, int len)
+{
+	int actual = 0;
+
+	/* Tx FIFO should be empty */
+	if (!(inb(iobase + UART_LSR) & UART_LSR_THRE))
+		return 0;
+
+	/* Fill FIFO with current frame */
+	while ((fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb(buf[actual], iobase + UART_TX);
+		actual++;
+	}
+
+	return actual;
+}
+
+
+static void dtl1_write_wakeup(dtl1_info_t *info)
+{
+	if (!info) {
+		printk(KERN_WARNING "dtl1_cs: Call of write_wakeup for unknown device.\n");
+		return;
+	}
+
+	if (test_bit(XMIT_WAITING, &(info->tx_state))) {
+		set_bit(XMIT_WAKEUP, &(info->tx_state));
+		return;
+	}
+
+	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
+		set_bit(XMIT_WAKEUP, &(info->tx_state));
+		return;
+	}
+
+	do {
+		register unsigned int iobase = info->link.io.BasePort1;
+		register struct sk_buff *skb;
+		register int len;
+
+		clear_bit(XMIT_WAKEUP, &(info->tx_state));
+
+		if (!(info->link.state & DEV_PRESENT))
+			return;
+
+		if (!(skb = skb_dequeue(&(info->txq))))
+			break;
+
+		/* Send frame */
+		len = dtl1_write(iobase, 32, skb->data, skb->len);
+
+		if (len == skb->len) {
+			set_bit(XMIT_WAITING, &(info->tx_state));
+			kfree_skb(skb);
+		} else {
+			skb_pull(skb, len);
+			skb_queue_head(&(info->txq), skb);
+		}
+
+		info->hdev.stat.byte_tx += len;
+
+	} while (test_bit(XMIT_WAKEUP, &(info->tx_state)));
+
+	clear_bit(XMIT_SENDING, &(info->tx_state));
+}
+
+
+static void dtl1_control(dtl1_info_t *info, struct sk_buff *skb)
+{
+	u8 flowmask = *(u8 *)skb->data;
+	int i;
+
+	printk(KERN_INFO "dtl1_cs: Nokia control data = ");
+	for (i = 0; i < skb->len; i++) {
+		printk("%02x ", skb->data[i]);
+	}
+	printk("\n");
+
+	/* transition to active state */
+	if (((info->flowmask & 0x07) == 0) && ((flowmask & 0x07) != 0)) {
+		clear_bit(XMIT_WAITING, &(info->tx_state));
+		dtl1_write_wakeup(info);
+	}
+
+	info->flowmask = flowmask;
+
+	kfree_skb(skb);
+}
+
+
+static void dtl1_receive(dtl1_info_t *info)
+{
+	unsigned int iobase;
+	nsh_t *nsh;
+	int boguscount = 0;
+
+	if (!info) {
+		printk(KERN_WARNING "dtl1_cs: Call of receive for unknown device.\n");
+		return;
+	}
+
+	iobase = info->link.io.BasePort1;
+
+	do {
+		info->hdev.stat.byte_rx++;
+
+		/* Allocate packet */
+		if (info->rx_skb == NULL)
+			if (!(info->rx_skb = bluez_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC))) {
+				printk(KERN_WARNING "dtl1_cs: Can't allocate mem for new packet.\n");
+				info->rx_state = RECV_WAIT_NSH;
+				info->rx_count = NSHL;
+				return;
+			}
+
+		*skb_put(info->rx_skb, 1) = inb(iobase + UART_RX);
+		nsh = (nsh_t *)info->rx_skb->data;
+
+		info->rx_count--;
+
+		if (info->rx_count == 0) {
+
+			switch (info->rx_state) {
+			case RECV_WAIT_NSH:
+				info->rx_state = RECV_WAIT_DATA;
+				info->rx_count = nsh->len + (nsh->len & 0x0001);
+				break;
+			case RECV_WAIT_DATA:
+				info->rx_skb->pkt_type = nsh->type;
+
+				/* remove PAD byte if it exists */
+				if (nsh->len & 0x0001) {
+					info->rx_skb->tail--;
+					info->rx_skb->len--;
+				}
+
+				/* remove NSH */
+				skb_pull(info->rx_skb, NSHL);
+
+				switch (info->rx_skb->pkt_type) {
+				case 0x80:
+					/* control data for the Nokia Card */
+					dtl1_control(info, info->rx_skb);
+					break;
+				case 0x82:
+				case 0x83:
+				case 0x84:
+					/* send frame to the HCI layer */
+					info->rx_skb->dev = (void *)&(info->hdev);
+					info->rx_skb->pkt_type &= 0x0f;
+					hci_recv_frame(info->rx_skb);
+					break;
+				default:
+					/* unknown packet */
+					printk(KERN_WARNING "dtl1_cs: Unknown HCI packet with type 0x%02x received.\n", info->rx_skb->pkt_type);
+					kfree_skb(info->rx_skb);
+					break;
+				}
+
+				info->rx_state = RECV_WAIT_NSH;
+				info->rx_count = NSHL;
+				info->rx_skb = NULL;
+				break;
+			}
+
+		}
+
+		/* Make sure we don't stay here to long */
+		if (boguscount++ > 32)
+			break;
+
+	} while (inb(iobase + UART_LSR) & UART_LSR_DR);
+}
+
+
+void dtl1_interrupt(int irq, void *dev_inst, struct pt_regs *regs)
+{
+	dtl1_info_t *info = dev_inst;
+	unsigned int iobase;
+	unsigned char msr;
+	int boguscount = 0;
+	int iir, lsr;
+
+	if (!info) {
+		printk(KERN_WARNING "dtl1_cs: Call of irq %d for unknown device.\n", irq);
+		return;
+	}
+
+	iobase = info->link.io.BasePort1;
+
+	spin_lock(&(info->lock));
+
+	iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+	while (iir) {
+
+		/* Clear interrupt */
+		lsr = inb(iobase + UART_LSR);
+
+		switch (iir) {
+		case UART_IIR_RLSI:
+			printk(KERN_NOTICE "dtl1_cs: RLSI\n");
+			break;
+		case UART_IIR_RDI:
+			/* Receive interrupt */
+			dtl1_receive(info);
+			break;
+		case UART_IIR_THRI:
+			if (lsr & UART_LSR_THRE) {
+				/* Transmitter ready for data */
+				dtl1_write_wakeup(info);
+			}
+			break;
+		default:
+			printk(KERN_NOTICE "dtl1_cs: Unhandled IIR=%#x\n", iir);
+			break;
+		}
+
+		/* Make sure we don't stay here to long */
+		if (boguscount++ > 100)
+			break;
+
+		iir = inb(iobase + UART_IIR) & UART_IIR_ID;
+
+	}
+
+	msr = inb(iobase + UART_MSR);
+
+	if (info->ri_latch ^ (msr & UART_MSR_RI)) {
+		info->ri_latch = msr & UART_MSR_RI;
+		clear_bit(XMIT_WAITING, &(info->tx_state));
+		dtl1_write_wakeup(info);
+	}
 
+	spin_unlock(&(info->lock));
 }
 
 
@@ -401,107 +371,94 @@
 /* ======================== HCI interface ======================== */
 
 
-static int dtl1_hci_open(struct hci_dev *hdev) {
-
-  set_bit(HCI_RUNNING, &(hdev->flags));
-
-
-  return 0;
+static int dtl1_hci_open(struct hci_dev *hdev)
+{
+	set_bit(HCI_RUNNING, &(hdev->flags));
 
+	return 0;
 }
 
 
-static int dtl1_hci_flush(struct hci_dev *hdev) {
-
-  dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
-
-
-  /* Drop TX queue */
-  skb_queue_purge(&(info->txq));
-
+static int dtl1_hci_flush(struct hci_dev *hdev)
+{
+	dtl1_info_t *info = (dtl1_info_t *)(hdev->driver_data);
 
-  return 0;
+	/* Drop TX queue */
+	skb_queue_purge(&(info->txq));
 
+	return 0;
 }
 
 
-static int dtl1_hci_close(struct hci_dev *hdev) {
+static int dtl1_hci_close(struct hci_dev *hdev)
+{
+	if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
+		return 0;
 
-  if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
-    return 0;
-
-
-  dtl1_hci_flush(hdev);
-
-
-  return 0;
+	dtl1_hci_flush(hdev);
 
+	return 0;
 }
 
 
-static int dtl1_hci_send_frame(struct sk_buff *skb) {
-
-  dtl1_info_t *info;
-  struct hci_dev* hdev = (struct hci_dev *)(skb->dev);
-  struct sk_buff *s;
-  nsh_t nsh;
-
+static int dtl1_hci_send_frame(struct sk_buff *skb)
+{
+	dtl1_info_t *info;
+	struct hci_dev *hdev = (struct hci_dev *)(skb->dev);
+	struct sk_buff *s;
+	nsh_t nsh;
 
-  if (!hdev) {
-    printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL).");
-    return -ENODEV;
-  }
+	if (!hdev) {
+		printk(KERN_WARNING "dtl1_cs: Frame for unknown HCI device (hdev=NULL).");
+		return -ENODEV;
+	}
 
-  info = (dtl1_info_t *)(hdev->driver_data);
+	info = (dtl1_info_t *)(hdev->driver_data);
 
+	switch (skb->pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		nsh.type = 0x81;
+		break;
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		nsh.type = 0x82;
+		break;
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		nsh.type = 0x83;
+		break;
+	};
 
-  switch (skb->pkt_type) {
-  case HCI_COMMAND_PKT:
-    hdev->stat.cmd_tx++;
-    nsh.type = 0x81;
-    break;
-  case HCI_ACLDATA_PKT:
-    hdev->stat.acl_tx++;
-    nsh.type = 0x82;
-    break;
-  case HCI_SCODATA_PKT:
-    hdev->stat.sco_tx++;
-    nsh.type = 0x83;
-    break;
-  };
+	nsh.zero = 0;
+	nsh.len = skb->len;
 
-  nsh.zero = 0;
-  nsh.len = skb->len;
+	s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
+	skb_reserve(s, NSHL);
+	memcpy(skb_put(s, skb->len), skb->data, skb->len);
+	if (skb->len & 0x0001)
+		*skb_put(s, 1) = 0;	/* PAD */
 
-  s = bluez_skb_alloc(NSHL + skb->len + 1, GFP_ATOMIC);
-  skb_reserve(s, NSHL);
-  memcpy(skb_put(s, skb->len), skb->data, skb->len);
-  if (skb->len & 0x0001)
-    *skb_put(s, 1) = 0;  /* PAD */
+	/* Prepend skb with Nokia frame header and queue */
+	memcpy(skb_push(s, NSHL), &nsh, NSHL);
+	skb_queue_tail(&(info->txq), s);
 
-  /* Prepend skb with Nokia frame header and queue */
-  memcpy(skb_push(s, NSHL), &nsh, NSHL);
-  skb_queue_tail(&(info->txq), s);
+	dtl1_write_wakeup(info);
 
+	kfree_skb(skb);
 
-  dtl1_write_wakeup(info);
-
-  kfree_skb(skb);
-
-
-  return 0;
-
+	return 0;
 }
 
 
-static void dtl1_hci_destruct(struct hci_dev *hdev) {
+static void dtl1_hci_destruct(struct hci_dev *hdev)
+{
 }
 
 
-static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) {
-
-  return -ENOIOCTLCMD;
-
+static int dtl1_hci_ioctl(struct hci_dev *hdev, unsigned int cmd,  unsigned long arg)
+{
+	return -ENOIOCTLCMD;
 }
 
 
@@ -509,101 +466,91 @@
 /* ======================== Card services HCI interaction ======================== */
 
 
-int dtl1_open(dtl1_info_t *info) {
+int dtl1_open(dtl1_info_t *info)
+{
+	unsigned long flags;
+	unsigned int iobase = info->link.io.BasePort1;
+	struct hci_dev *hdev;
 
-  unsigned long flags;
-  unsigned int iobase = info->link.io.BasePort1;
-  struct hci_dev *hdev;
+	spin_lock_init(&(info->lock));
 
+	skb_queue_head_init(&(info->txq));
 
-  spin_lock_init(&(info->lock));
+	info->rx_state = RECV_WAIT_NSH;
+	info->rx_count = NSHL;
+	info->rx_skb = NULL;
 
-  skb_queue_head_init(&(info->txq));
+	set_bit(XMIT_WAITING, &(info->tx_state));
 
-  info->rx_state = RECV_WAIT_NSH;
-  info->rx_count = NSHL;
-  info->rx_skb = NULL;
+	spin_lock_irqsave(&(info->lock), flags);
 
-  set_bit(XMIT_WAITING, &(info->tx_state));
+	/* Reset UART */
+	outb(0, iobase + UART_MCR);
 
+	/* Turn off interrupts */
+	outb(0, iobase + UART_IER);
 
-  spin_lock_irqsave(&(info->lock), flags);
+	/* Initialize UART */
+	outb(UART_LCR_WLEN8, iobase + UART_LCR);	/* Reset DLAB */
+	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
 
-  /* Reset UART */
-  outb(0, iobase + UART_MCR);
+	info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
 
-  /* Turn off interrupts */
-  outb(0, iobase + UART_IER);
+	/* Turn on interrupts */
+	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
 
-  /* Initialize UART */
-  outb(UART_LCR_WLEN8, iobase + UART_LCR);  /* Reset DLAB */
-  outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase + UART_MCR);
+	spin_unlock_irqrestore(&(info->lock), flags);
 
-  info->ri_latch = inb(info->link.io.BasePort1 + UART_MSR) & UART_MSR_RI;
+	/* Timeout before it is safe to send the first HCI packet */
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(HZ * 2);
 
-  /* Turn on interrupts */
-  outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
 
-  spin_unlock_irqrestore(&(info->lock), flags);
+	/* Initialize and register HCI device */
 
+	hdev = &(info->hdev);
 
-  /* Timeout before it is safe to send the first HCI packet */
-  set_current_state(TASK_INTERRUPTIBLE);
-  schedule_timeout(HZ * 2);
+	hdev->type = HCI_PCCARD;
+	hdev->driver_data = info;
 
+	hdev->open = dtl1_hci_open;
+	hdev->close = dtl1_hci_close;
+	hdev->flush = dtl1_hci_flush;
+	hdev->send = dtl1_hci_send_frame;
+	hdev->destruct = dtl1_hci_destruct;
+	hdev->ioctl = dtl1_hci_ioctl;
 
-  /* Initialize and register HCI device */
-
-  hdev = &(info->hdev);
-
-  hdev->type = HCI_PCCARD;
-  hdev->driver_data = info;
-
-  hdev->open     = dtl1_hci_open;
-  hdev->close    = dtl1_hci_close;
-  hdev->flush    = dtl1_hci_flush;
-  hdev->send     = dtl1_hci_send_frame;
-  hdev->destruct = dtl1_hci_destruct;
-  hdev->ioctl    = dtl1_hci_ioctl;
-
-  if (hci_register_dev(hdev) < 0) {
-    printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
-    return -ENODEV;
-  }
-
-
-  return 0;
+	if (hci_register_dev(hdev) < 0) {
+		printk(KERN_WARNING "dtl1_cs: Can't register HCI device %s.\n", hdev->name);
+		return -ENODEV;
+	}
 
+	return 0;
 }
 
 
-int dtl1_close(dtl1_info_t *info) {
-
-  unsigned long flags;
-  unsigned int iobase = info->link.io.BasePort1;
-  struct hci_dev *hdev = &(info->hdev);
-
-
-  dtl1_hci_close(hdev);
-
-
-  spin_lock_irqsave(&(info->lock), flags);
-
-  /* Reset UART */
-  outb(0, iobase + UART_MCR);
+int dtl1_close(dtl1_info_t *info)
+{
+	unsigned long flags;
+	unsigned int iobase = info->link.io.BasePort1;
+	struct hci_dev *hdev = &(info->hdev);
 
-  /* Turn off interrupts */
-  outb(0, iobase + UART_IER);
+	dtl1_hci_close(hdev);
 
-  spin_unlock_irqrestore(&(info->lock), flags);
+	spin_lock_irqsave(&(info->lock), flags);
 
+	/* Reset UART */
+	outb(0, iobase + UART_MCR);
 
-  if (hci_unregister_dev(hdev) < 0)
-    printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name);
+	/* Turn off interrupts */
+	outb(0, iobase + UART_IER);
 
+	spin_unlock_irqrestore(&(info->lock), flags);
 
-  return 0;
+	if (hci_unregister_dev(hdev) < 0)
+		printk(KERN_WARNING "dtl1_cs: Can't unregister HCI device %s.\n", hdev->name);
 
+	return 0;
 }
 
 
@@ -611,291 +558,267 @@
 /* ======================== Card services ======================== */
 
 
-static void cs_error(client_handle_t handle, int func, int ret) {
-
-  error_info_t err = { func, ret };
-
-
-  CardServices(ReportError, handle, &err);
-
-}
-
-
-dev_link_t *dtl1_attach(void) {
-
-  dtl1_info_t *info;
-  client_reg_t client_reg;
-  dev_link_t *link;
-  int i, ret;
-
-
-  /* Create new info device */
-  info = kmalloc(sizeof(*info), GFP_KERNEL);
-  if (!info)
-    return NULL;
-  memset(info, 0, sizeof(*info));
-
-
-  link = &info->link;
-  link->priv = info;
-
-  link->release.function = &dtl1_release;
-  link->release.data = (u_long)link;
-  link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
-  link->io.NumPorts1 = 8;
-  link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-  link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
-
-  if (irq_list[0] == -1)
-    link->irq.IRQInfo2 = irq_mask;
-  else
-    for (i = 0; i < 4; i++)
-      link->irq.IRQInfo2 |= 1 << irq_list[i];
-
-  link->irq.Handler = dtl1_interrupt;
-  link->irq.Instance = info;
-
-  link->conf.Attributes = CONF_ENABLE_IRQ;
-  link->conf.Vcc = 50;
-  link->conf.IntType = INT_MEMORY_AND_IO;
-
-
-  /* Register with Card Services */
-  link->next = dev_list;
-  dev_list = link;
-  client_reg.dev_info = &dev_info;
-  client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
-  client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
-                         CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
-                         CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
-  client_reg.event_handler = &dtl1_event;
-  client_reg.Version = 0x0210;
-  client_reg.event_callback_args.client_data = link;
-
-  ret = CardServices(RegisterClient, &link->handle, &client_reg);
-  if (ret != CS_SUCCESS) {
-    cs_error(link->handle, RegisterClient, ret);
-    dtl1_detach(link);
-    return NULL;
-  }
-
-
-  return link;
-
-}
-
-
-void dtl1_detach(dev_link_t *link) {
-
-  dtl1_info_t *info = link->priv;
-  dev_link_t **linkp;
-  int ret;
-
-
-  /* Locate device structure */
-  for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
-    if (*linkp == link)
-      break;
-
-  if (*linkp == NULL)
-    return;
-
-
-  del_timer(&link->release);
-  if (link->state & DEV_CONFIG)
-    dtl1_release((u_long)link);
-
-
-  if (link->handle) {
-    ret = CardServices(DeregisterClient, link->handle);
-    if (ret != CS_SUCCESS)
-      cs_error(link->handle, DeregisterClient, ret);
-  }
-
-
-  /* Unlink device structure, free bits */
-  *linkp = link->next;
-
-  kfree(info);
-
-}
-
-
-static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
-		     cisparse_t *parse) {
-
-  int i;
-
-
-  i = CardServices(fn, handle, tuple);
-  if (i != CS_SUCCESS)
-    return CS_NO_MORE_ITEMS;
-
-  i = CardServices(GetTupleData, handle, tuple);
-  if (i != CS_SUCCESS)
-    return i;
-
-  return CardServices(ParseTuple, handle, tuple, parse);
+static void cs_error(client_handle_t handle, int func, int ret)
+{
+	error_info_t err = { func, ret };
+
+	CardServices(ReportError, handle, &err);
+}
+
+
+dev_link_t *dtl1_attach(void)
+{
+	dtl1_info_t *info;
+	client_reg_t client_reg;
+	dev_link_t *link;
+	int i, ret;
+
+	/* Create new info device */
+	info = kmalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return NULL;
+	memset(info, 0, sizeof(*info));
+
+	link = &info->link;
+	link->priv = info;
+
+	link->release.function = &dtl1_release;
+	link->release.data = (u_long)link;
+	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+	link->io.NumPorts1 = 8;
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
+	link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
+
+	if (irq_list[0] == -1)
+		link->irq.IRQInfo2 = irq_mask;
+	else
+		for (i = 0; i < 4; i++)
+			link->irq.IRQInfo2 |= 1 << irq_list[i];
+
+	link->irq.Handler = dtl1_interrupt;
+	link->irq.Instance = info;
+
+	link->conf.Attributes = CONF_ENABLE_IRQ;
+	link->conf.Vcc = 50;
+	link->conf.IntType = INT_MEMORY_AND_IO;
+
+	/* Register with Card Services */
+	link->next = dev_list;
+	dev_list = link;
+	client_reg.dev_info = &dev_info;
+	client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+	client_reg.EventMask =
+		CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+		CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+		CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+	client_reg.event_handler = &dtl1_event;
+	client_reg.Version = 0x0210;
+	client_reg.event_callback_args.client_data = link;
+
+	ret = CardServices(RegisterClient, &link->handle, &client_reg);
+	if (ret != CS_SUCCESS) {
+		cs_error(link->handle, RegisterClient, ret);
+		dtl1_detach(link);
+		return NULL;
+	}
+
+	return link;
+}
+
+
+void dtl1_detach(dev_link_t *link)
+{
+	dtl1_info_t *info = link->priv;
+	dev_link_t **linkp;
+	int ret;
+
+	/* Locate device structure */
+	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
+		if (*linkp == link)
+			break;
+
+	if (*linkp == NULL)
+		return;
+
+	del_timer(&link->release);
+	if (link->state & DEV_CONFIG)
+		dtl1_release((u_long)link);
+
+	if (link->handle) {
+		ret = CardServices(DeregisterClient, link->handle);
+		if (ret != CS_SUCCESS)
+			cs_error(link->handle, DeregisterClient, ret);
+	}
+
+	/* Unlink device structure, free bits */
+	*linkp = link->next;
+
+	kfree(info);
+}
+
+
+static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
+{
+	int i;
+
+	i = CardServices(fn, handle, tuple);
+	if (i != CS_SUCCESS)
+		return CS_NO_MORE_ITEMS;
+
+	i = CardServices(GetTupleData, handle, tuple);
+	if (i != CS_SUCCESS)
+		return i;
 
+	return CardServices(ParseTuple, handle, tuple, parse);
 }
 
 
 #define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
 #define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
 
-void dtl1_config(dev_link_t *link) {
-
-  client_handle_t handle = link->handle;
-  dtl1_info_t *info = link->priv;
-  tuple_t tuple;
-  u_short buf[256];
-  cisparse_t parse;
-  cistpl_cftable_entry_t *cf = &parse.cftable_entry;
-  config_info_t config;
-  int i, last_ret, last_fn;
-
-
-  tuple.TupleData = (cisdata_t *)buf;
-  tuple.TupleOffset = 0;
-  tuple.TupleDataMax = 255;
-  tuple.Attributes = 0;
-
-  /* Get configuration register information */
-  tuple.DesiredTuple = CISTPL_CONFIG;
-  last_ret = first_tuple(handle, &tuple, &parse);
-  if (last_ret != CS_SUCCESS) {
-    last_fn = ParseTuple;
-    goto cs_failed;
-  }
-  link->conf.ConfigBase = parse.config.base;
-  link->conf.Present = parse.config.rmask[0];
-
-
-  /* Configure card */
-  link->state |= DEV_CONFIG;
-  i = CardServices(GetConfigurationInfo, handle, &config);
-  link->conf.Vcc = config.Vcc;
-
-  tuple.TupleData = (cisdata_t *)buf;
-  tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-  tuple.Attributes = 0;
-  tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-
-  /* Look for a generic full-sized window */
-  link->io.NumPorts1 = 8;
-  i = first_tuple(handle, &tuple, &parse);
-  while (i != CS_NO_MORE_ITEMS) {
-    if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
-      link->conf.ConfigIndex = cf->index;
-      link->io.BasePort1 = cf->io.win[0].base;
-      link->io.NumPorts1 = cf->io.win[0].len; /*yo*/
-      link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
-      i = CardServices(RequestIO, link->handle, &link->io);
-      if (i == CS_SUCCESS)
-        break;
-    }
-    i = next_tuple(handle, &tuple, &parse);
-  }
-
-  if (i != CS_SUCCESS) {
-    cs_error(link->handle, RequestIO, i);
-    goto failed;
-  }
-
-  i = CardServices(RequestIRQ, link->handle, &link->irq);
-  if (i != CS_SUCCESS) {
-    cs_error(link->handle, RequestIRQ, i);
-    link->irq.AssignedIRQ = 0;
-  }
-
-  i = CardServices(RequestConfiguration, link->handle, &link->conf);
-  if (i != CS_SUCCESS) {
-    cs_error(link->handle, RequestConfiguration, i);
-    goto failed;
-  }
-
-
-  MOD_INC_USE_COUNT;
-
-  if (dtl1_open(info) != 0)
-    goto failed;
-
-
-  link->dev = &info->node;
-  link->state &= ~DEV_CONFIG_PENDING;
-
-
-  return;
+void dtl1_config(dev_link_t *link)
+{
+	client_handle_t handle = link->handle;
+	dtl1_info_t *info = link->priv;
+	tuple_t tuple;
+	u_short buf[256];
+	cisparse_t parse;
+	cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+	config_info_t config;
+	int i, last_ret, last_fn;
+
+	tuple.TupleData = (cisdata_t *)buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 255;
+	tuple.Attributes = 0;
+
+	/* Get configuration register information */
+	tuple.DesiredTuple = CISTPL_CONFIG;
+	last_ret = first_tuple(handle, &tuple, &parse);
+	if (last_ret != CS_SUCCESS) {
+		last_fn = ParseTuple;
+		goto cs_failed;
+	}
+	link->conf.ConfigBase = parse.config.base;
+	link->conf.Present = parse.config.rmask[0];
+
+	/* Configure card */
+	link->state |= DEV_CONFIG;
+	i = CardServices(GetConfigurationInfo, handle, &config);
+	link->conf.Vcc = config.Vcc;
+
+	tuple.TupleData = (cisdata_t *)buf;
+	tuple.TupleOffset = 0;
+	tuple.TupleDataMax = 255;
+	tuple.Attributes = 0;
+	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+
+	/* Look for a generic full-sized window */
+	link->io.NumPorts1 = 8;
+	i = first_tuple(handle, &tuple, &parse);
+	while (i != CS_NO_MORE_ITEMS) {
+		if ((i == CS_SUCCESS) && (cf->io.nwin == 1) && (cf->io.win[0].len > 8)) {
+			link->conf.ConfigIndex = cf->index;
+			link->io.BasePort1 = cf->io.win[0].base;
+			link->io.NumPorts1 = cf->io.win[0].len;	/*yo */
+			link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;
+			i = CardServices(RequestIO, link->handle, &link->io);
+			if (i == CS_SUCCESS)
+				break;
+		}
+		i = next_tuple(handle, &tuple, &parse);
+	}
+
+	if (i != CS_SUCCESS) {
+		cs_error(link->handle, RequestIO, i);
+		goto failed;
+	}
+
+	i = CardServices(RequestIRQ, link->handle, &link->irq);
+	if (i != CS_SUCCESS) {
+		cs_error(link->handle, RequestIRQ, i);
+		link->irq.AssignedIRQ = 0;
+	}
+
+	i = CardServices(RequestConfiguration, link->handle, &link->conf);
+	if (i != CS_SUCCESS) {
+		cs_error(link->handle, RequestConfiguration, i);
+		goto failed;
+	}
+
+	MOD_INC_USE_COUNT;
+
+	if (dtl1_open(info) != 0)
+		goto failed;
+
+	strcpy(info->node.dev_name, info->hdev.name);
+	link->dev = &info->node;
+	link->state &= ~DEV_CONFIG_PENDING;
 
+	return;
 
 cs_failed:
-  cs_error(link->handle, last_fn, last_ret);
-failed:
-  dtl1_release((u_long)link);
+	cs_error(link->handle, last_fn, last_ret);
 
+failed:
+	dtl1_release((u_long)link);
 }
 
 
-void dtl1_release(u_long arg) {
-
-  dev_link_t *link = (dev_link_t *)arg;
-  dtl1_info_t *info = link->priv;
-
-
-  if (link->state & DEV_PRESENT)
-    dtl1_close(info);
-
-  MOD_DEC_USE_COUNT;
-
-
-  link->dev = NULL;
-
-  CardServices(ReleaseConfiguration, link->handle);
-  CardServices(ReleaseIO, link->handle, &link->io);
-  CardServices(ReleaseIRQ, link->handle, &link->irq);
-
-  link->state &= ~DEV_CONFIG;
-
+void dtl1_release(u_long arg)
+{
+	dev_link_t *link = (dev_link_t *)arg;
+	dtl1_info_t *info = link->priv;
+
+	if (link->state & DEV_PRESENT)
+		dtl1_close(info);
+
+	MOD_DEC_USE_COUNT;
+
+	link->dev = NULL;
+
+	CardServices(ReleaseConfiguration, link->handle);
+	CardServices(ReleaseIO, link->handle, &link->io);
+	CardServices(ReleaseIRQ, link->handle, &link->irq);
+
+	link->state &= ~DEV_CONFIG;
 }
 
 
-int dtl1_event(event_t event, int priority, event_callback_args_t *args) {
-
-  dev_link_t *link = args->client_data;
-  dtl1_info_t *info = link->priv;
-
-
-  switch (event) {
-  case CS_EVENT_CARD_REMOVAL:
-    link->state &= ~DEV_PRESENT;
-    if (link->state & DEV_CONFIG) {
-      dtl1_close(info);
-      mod_timer(&link->release, jiffies + HZ/20);
-    }
-    break;
-  case CS_EVENT_CARD_INSERTION:
-    link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
-    dtl1_config(link);
-    break;
-  case CS_EVENT_PM_SUSPEND:
-    link->state |= DEV_SUSPEND;
-    /* Fall through... */
-  case CS_EVENT_RESET_PHYSICAL:
-    if (link->state & DEV_CONFIG)
-      CardServices(ReleaseConfiguration, link->handle);
-    break;
-  case CS_EVENT_PM_RESUME:
-    link->state &= ~DEV_SUSPEND;
-    /* Fall through... */
-  case CS_EVENT_CARD_RESET:
-    if (DEV_OK(link))
-      CardServices(RequestConfiguration, link->handle, &link->conf);
-    break;
-  }
-
-
-  return 0;
+int dtl1_event(event_t event, int priority, event_callback_args_t *args)
+{
+	dev_link_t *link = args->client_data;
+	dtl1_info_t *info = link->priv;
+
+	switch (event) {
+	case CS_EVENT_CARD_REMOVAL:
+		link->state &= ~DEV_PRESENT;
+		if (link->state & DEV_CONFIG) {
+			dtl1_close(info);
+			mod_timer(&link->release, jiffies + HZ / 20);
+		}
+		break;
+	case CS_EVENT_CARD_INSERTION:
+		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+		dtl1_config(link);
+		break;
+	case CS_EVENT_PM_SUSPEND:
+		link->state |= DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_RESET_PHYSICAL:
+		if (link->state & DEV_CONFIG)
+			CardServices(ReleaseConfiguration, link->handle);
+		break;
+	case CS_EVENT_PM_RESUME:
+		link->state &= ~DEV_SUSPEND;
+		/* Fall through... */
+	case CS_EVENT_CARD_RESET:
+		if (DEV_OK(link))
+			CardServices(RequestConfiguration, link->handle, &link->conf);
+		break;
+	}
 
+	return 0;
 }
 
 
@@ -903,33 +826,29 @@
 /* ======================== Module initialization ======================== */
 
 
-int __init init_dtl1_cs(void) {
+int __init init_dtl1_cs(void)
+{
+	servinfo_t serv;
+	int err;
 
-  servinfo_t serv;
-  int err;
+	CardServices(GetCardServicesInfo, &serv);
+	if (serv.Revision != CS_RELEASE_CODE) {
+		printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
+		return -1;
+	}
 
+	err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
 
-  CardServices(GetCardServicesInfo, &serv);
-  if (serv.Revision != CS_RELEASE_CODE) {
-    printk(KERN_NOTICE "dtl1_cs: Card Services release does not match!\n");
-    return -1;
-  }
-
-
-  err = register_pccard_driver(&dev_info, &dtl1_attach, &dtl1_detach);
-
-
-  return err;
-
+	return err;
 }
 
-void __exit exit_dtl1_cs(void) {
-
-  unregister_pccard_driver(&dev_info);
 
-  while (dev_list != NULL)
-    dtl1_detach(dev_list);
+void __exit exit_dtl1_cs(void)
+{
+	unregister_pccard_driver(&dev_info);
 
+	while (dev_list != NULL)
+		dtl1_detach(dev_list);
 }
 
 
diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/cdrom/aztcd.c	Thu Aug  1 14:17:41 2002
@@ -1931,7 +1931,7 @@
 	}
 	devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
 		       S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL);
-	if (devfs_register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) {
+	if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) {
 		printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech"
 		       " CD-ROM\n", MAJOR_NR);
 		ret = -EIO;
@@ -1957,9 +1957,8 @@
 
 void __exit aztcd_exit(void)
 {
-	devfs_unregister(devfs_find_handle
-			 (NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0));
-	if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
+	devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
 		printk("What's that: can't unregister aztcd\n");
 		return;
 	}
diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c
--- a/drivers/cdrom/cdu31a.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/cdrom/cdu31a.c	Thu Aug  1 14:17:36 2002
@@ -3367,7 +3367,7 @@
 		if (!request_region(cdu31a_port, 4, "cdu31a"))
 			goto errout3;
 
-		if (devfs_register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) {
+		if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) {
 			printk("Unable to get major %d for CDU-31a\n",
 			       MAJOR_NR);
 			goto errout2;
@@ -3460,7 +3460,7 @@
       errout0:
 	printk("Unable to register CDU-31a with Uniform cdrom driver\n");
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-	if (devfs_unregister_blkdev(MAJOR_NR, "cdu31a")) {
+	if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
 		printk("Can't unregister block device for cdu31a\n");
 	}
       errout2:
@@ -3477,7 +3477,7 @@
 		    ("Can't unregister cdu31a from Uniform cdrom driver\n");
 		return;
 	}
-	if ((devfs_unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
+	if ((unregister_blkdev(MAJOR_NR, "cdu31a") == -EINVAL)) {
 		printk("Can't unregister cdu31a\n");
 		return;
 	}
diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
--- a/drivers/cdrom/cm206.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/cdrom/cm206.c	Thu Aug  1 14:17:40 2002
@@ -1367,7 +1367,7 @@
 			printk("Can't unregister cdrom cm206\n");
 			return;
 		}
-		if (devfs_unregister_blkdev(MAJOR_NR, "cm206")) {
+		if (unregister_blkdev(MAJOR_NR, "cm206")) {
 			printk("Can't unregister major cm206\n");
 			return;
 		}
@@ -1490,7 +1490,7 @@
 		return -EIO;
 	}
 	printk(".\n");
-	if (devfs_register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
+	if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) {
 		printk(KERN_INFO "Cannot register for major %d!\n",
 		       MAJOR_NR);
 		cleanup(3);
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/cdrom/gscd.c	Thu Aug  1 14:17:36 2002
@@ -933,9 +933,8 @@
 {
 	CLEAR_TIMER;
 
-	devfs_unregister(devfs_find_handle
-			 (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0));
-	if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
+	devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
 		printk("What's that: can't unregister GoldStar-module\n");
 		return;
 	}
@@ -1013,7 +1012,7 @@
 		i++;
 	}
 
-	if (devfs_register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
+	if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
 		printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar "
 		       "CD-ROM\n", MAJOR_NR);
 		ret = -EIO;
diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
--- a/drivers/cdrom/mcd.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/cdrom/mcd.c	Thu Aug  1 14:17:36 2002
@@ -1039,7 +1039,7 @@
 	case 2:
 		release_region(mcd_port, 4);
 	case 1:
-		if (devfs_unregister_blkdev(MAJOR_NR, "mcd")) {
+		if (unregister_blkdev(MAJOR_NR, "mcd")) {
 			printk(KERN_WARNING "Can't unregister major mcd\n");
 			return;
 		}
@@ -1065,7 +1065,7 @@
 		return -EIO;
 	}
 
-	if (devfs_register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
+	if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
 		printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
 		return -EIO;
 	}
diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c
--- a/drivers/cdrom/mcdx.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/cdrom/mcdx.c	Thu Aug  1 14:17:40 2002
@@ -1166,7 +1166,7 @@
 	}
 
 	xtrace(INIT, "init() register blkdev\n");
-	if (devfs_register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {
+	if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) {
 		release_region((unsigned long) stuffp->wreg_data,
 			       MCDX_IO_SIZE);
 		xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
@@ -1222,7 +1222,7 @@
 			       MCDX_IO_SIZE);
 		free_irq(stuffp->irq, NULL);
 		kfree(stuffp);
-		if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0)
+		if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
 			xwarn("cleanup() unregister_blkdev() failed\n");
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 		return 2;
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/cdrom/optcd.c	Thu Aug  1 14:17:39 2002
@@ -2031,8 +2031,7 @@
 		DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
 		return -EIO;
 	}
-	if (devfs_register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0)
-	{
+	if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) {
 		printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR);
 		release_region(optcd_port, 4);
 		return -EIO;
@@ -2051,9 +2050,8 @@
 
 void __exit optcd_exit(void)
 {
-	devfs_unregister(devfs_find_handle(NULL, "optcd", 0, 0,
-					   DEVFS_SPECIAL_BLK, 0));
-	if (devfs_unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
+	devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
+	if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
 		printk(KERN_ERR "optcd: what's that: can't unregister\n");
 		return;
 	}
diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
--- a/drivers/cdrom/sbpcd.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/cdrom/sbpcd.c	Thu Aug  1 14:17:36 2002
@@ -5771,7 +5771,7 @@
 	OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */
 #endif /* SOUND_BASE */
 
-	if (devfs_register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0)
+	if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0)
 	{
 		msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR);
 #ifdef MODULE
@@ -5806,7 +5806,7 @@
 		if (D_S[j].sbp_buf==NULL)
 		{
 			msg(DBG_INF,"data buffer (%d frames) not available.\n",D_S[j].sbp_bufsiz);
-			if ((devfs_unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
+			if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
 			{
 				printk("Can't unregister %s\n", major_name);
 			}
@@ -5858,7 +5858,7 @@
 {
 	int j;
 	
-	if ((devfs_unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
+	if ((unregister_blkdev(MAJOR_NR, major_name) == -EINVAL))
 	{
 		msg(DBG_INF, "What's that: can't unregister %s.\n", major_name);
 		return;
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/cdrom/sjcd.c	Thu Aug  1 14:17:41 2002
@@ -1680,7 +1680,7 @@
 	printk("SJCD: sjcd=0x%x: ", sjcd_base);
 #endif
 
-	if (devfs_register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
+	if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) {
 		printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n",
 		       MAJOR_NR);
 		return (-EIO);
@@ -1789,7 +1789,7 @@
 
 static int sjcd_cleanup(void)
 {
-	if ((devfs_unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
+	if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
 		printk("SJCD: cannot unregister device.\n");
 	else {
 		release_region(sjcd_base, 4);
@@ -1802,8 +1802,7 @@
 
 void __exit sjcd_exit(void)
 {
-	devfs_unregister(devfs_find_handle
-			 (NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0));
+	devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
 	if (sjcd_cleanup())
 		printk("SJCD: module: cannot be removed.\n");
 	else
diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
--- a/drivers/cdrom/sonycd535.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/cdrom/sonycd535.c	Thu Aug  1 14:17:40 2002
@@ -1572,7 +1572,7 @@
 								MAJOR_NR, 0,
 								S_IFBLK | S_IRUGO | S_IWUGO,
 								&cdu_fops, NULL);
-				if (devfs_register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
+				if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
 					printk("Unable to get major %d for %s\n",
 							MAJOR_NR, CDU535_MESSAGE_NAME);
 					return -EIO;
@@ -1585,7 +1585,7 @@
 					kmalloc(sizeof *sony_toc, GFP_KERNEL);
 				if (sony_toc == NULL) {
 					blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-					devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
+					unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
 					devfs_unregister(sony_devfs_handle);
 					return -ENOMEM;
 				}
@@ -1594,7 +1594,7 @@
 				if (last_sony_subcode == NULL) {
 					blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 					kfree(sony_toc);
-					devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
+					unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
 					devfs_unregister(sony_devfs_handle);
 					return -ENOMEM;
 				}
@@ -1604,7 +1604,7 @@
 					blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 					kfree(sony_toc);
 					kfree(last_sony_subcode);
-					devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
+					unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
 					devfs_unregister(sony_devfs_handle);
 					return -ENOMEM;
 				}
@@ -1618,7 +1618,7 @@
 						kfree(sony_buffer);
 						kfree(sony_toc);
 						kfree(last_sony_subcode);
-						devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
+						unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
 						devfs_unregister(sony_devfs_handle);
 						return -ENOMEM;
 					}
@@ -1643,7 +1643,7 @@
 		kfree(sony_buffer);
 		kfree(sony_toc);
 		kfree(last_sony_subcode);
-		devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
+		unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
 		devfs_unregister(sony_devfs_handle);
 		if (sony535_irq_used)
 			free_irq(sony535_irq_used, NULL);
@@ -1700,9 +1700,9 @@
 	kfree(sony_buffer);
 	kfree(last_sony_subcode);
 	kfree(sony_toc);
-	devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0,
-					   DEVFS_SPECIAL_BLK, 0));
-	if (devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
+	devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0,
+				  DEVFS_SPECIAL_BLK, 0);
+	if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
 		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
 	else
 		printk(KERN_INFO CDU535_HANDLE " module released\n");
diff -Nru a/drivers/char/Config.help b/drivers/char/Config.help
--- a/drivers/char/Config.help	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/Config.help	Thu Aug  1 14:17:40 2002
@@ -1110,3 +1110,9 @@
   pSeries machines when partitioned support a hypervisor virtual
   console. This driver allows each pSeries partition to have a console
   which is accessed via the HMC.
+
+CONFIG_RAW_DRIVER
+  The raw driver permits block devices to be bound to /dev/raw/rawN. 
+  Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 
+  See the raw(8) manpage for more details.
+
diff -Nru a/drivers/char/Config.in b/drivers/char/Config.in
--- a/drivers/char/Config.in	Thu Aug  1 14:17:37 2002
+++ b/drivers/char/Config.in	Thu Aug  1 14:17:37 2002
@@ -198,4 +198,6 @@
    tristate 'ACP Modem (Mwave) support' CONFIG_MWAVE
 fi
 
+tristate '  RAW driver (/dev/raw/rawN)' CONFIG_RAW_DRIVER
+
 endmenu
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/char/Makefile	Thu Aug  1 14:17:41 2002
@@ -7,7 +7,7 @@
 #
 FONTMAPFILE = cp437.uni
 
-obj-y	 += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o
+obj-y	 += mem.o tty_io.o n_tty.o tty_ioctl.o pty.o misc.o random.o
 
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
@@ -146,6 +146,7 @@
 obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o
 obj-$(CONFIG_SERIAL_TX3912) += generic_serial.o serial_tx3912.o
 obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o
+obj-$(CONFIG_RAW_DRIVER) += raw.o
 
 obj-$(CONFIG_PRINTER) += lp.o
 
diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
--- a/drivers/char/drm/mga_drv.h	Thu Aug  1 14:17:41 2002
+++ b/drivers/char/drm/mga_drv.h	Thu Aug  1 14:17:41 2002
@@ -38,7 +38,7 @@
 
 	u32 tail;
 	int space;
-	volatile int wrapped;
+	volatile long wrapped;
 
 	volatile u32 *status;
 
diff -Nru a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
--- a/drivers/char/dsp56k.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/dsp56k.c	Thu Aug  1 14:17:40 2002
@@ -510,7 +510,7 @@
 		return -ENODEV;
 	}
 
-	if(devfs_register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) {
+	if(register_chrdev(DSP56K_MAJOR, "dsp56k", &dsp56k_fops)) {
 		printk("DSP56k driver: Unable to register driver\n");
 		return -ENODEV;
 	}
@@ -526,7 +526,7 @@
 
 static void __exit dsp56k_cleanup_driver(void)
 {
-	devfs_unregister_chrdev(DSP56K_MAJOR, "dsp56k");
+	unregister_chrdev(DSP56K_MAJOR, "dsp56k");
 	devfs_unregister(devfs_handle);
 }
 module_exit(dsp56k_cleanup_driver);
diff -Nru a/drivers/char/dtlk.c b/drivers/char/dtlk.c
--- a/drivers/char/dtlk.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/dtlk.c	Thu Aug  1 14:17:40 2002
@@ -340,7 +340,7 @@
 	dtlk_port_lpc = 0;
 	dtlk_port_tts = 0;
 	dtlk_busy = 0;
-	dtlk_major = devfs_register_chrdev(0, "dtlk", &dtlk_fops);
+	dtlk_major = register_chrdev(0, "dtlk", &dtlk_fops);
 	if (dtlk_major == 0) {
 		printk(KERN_ERR "DoubleTalk PC - cannot register device\n");
 		return 0;
@@ -369,7 +369,7 @@
 						   signals... */
 
 	dtlk_write_tts(DTLK_CLEAR);
-	devfs_unregister_chrdev(dtlk_major, "dtlk");
+	unregister_chrdev(dtlk_major, "dtlk");
 	devfs_unregister(devfs_handle);
 	release_region(dtlk_port_lpc, DTLK_IO_EXTENT);
 }
diff -Nru a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
--- a/drivers/char/ftape/zftape/zftape-init.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/ftape/zftape/zftape-init.c	Thu Aug  1 14:17:40 2002
@@ -67,7 +67,7 @@
 
 /*      Local vars.
  */
-static int busy_flag;
+static unsigned long busy_flag;
 
 static sigset_t orig_sigmask;
 
@@ -345,7 +345,7 @@
 	TRACE(ft_t_info, "zft_init @ 0x%p", zft_init);
 	TRACE(ft_t_info,
 	      "installing zftape VFS interface for ftape driver ...");
-	TRACE_CATCH(devfs_register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
+	TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
 
 	for (i = 0; i < 4; i++) {
 		char devname[9];
@@ -419,24 +419,24 @@
 
 	TRACE_FUN(ft_t_flow);
 
-	if (devfs_unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
+	if (unregister_chrdev(QIC117_TAPE_MAJOR, "zft") != 0) {
 		TRACE(ft_t_warn, "failed");
 	} else {
 		TRACE(ft_t_info, "successful");
 	}
         for (i = 0; i < 4; i++) {
 		sprintf(devname, "qft%i", i);
-		devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0));
+		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i, DEVFS_SPECIAL_CHR, 0);
 		sprintf(devname, "nqft%i", i);
-		devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0));
+		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 4, DEVFS_SPECIAL_CHR, 0);
 		sprintf(devname, "zqft%i", i);
-		devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0));
+		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 16, DEVFS_SPECIAL_CHR, 0);
 		sprintf(devname, "nzqft%i", i);
-		devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0));
+		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 20, DEVFS_SPECIAL_CHR, 0);
 		sprintf(devname, "rawqft%i", i);
-		devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0));
+		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 32, DEVFS_SPECIAL_CHR, 0);
 		sprintf(devname, "nrawqft%i", i);
-		devfs_unregister(devfs_find_handle(NULL, devname, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0));
+		devfs_find_and_unregister(NULL, devname, QIC117_TAPE_MAJOR, i + 36, DEVFS_SPECIAL_CHR, 0);
 	}
 	zft_uninit_mem(); /* release remaining memory, if any */
         printk(KERN_INFO "zftape successfully unloaded.\n");
diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c
--- a/drivers/char/ip2main.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/char/ip2main.c	Thu Aug  1 14:17:41 2002
@@ -531,12 +531,7 @@
 	if ( ( err = tty_unregister_driver ( &ip2_callout_driver ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister callout driver (%d)\n", err);
 	}
-#ifdef	CONFIG_DEVFS_FS
-	if ( ( err = devfs_unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
-#else
-	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) )
-#endif
-	{
+	if ( ( err = unregister_chrdev ( IP2_IPL_MAJOR, pcIpl ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister IPL driver (%d)\n", err);
 	}
 	remove_proc_entry("ip2mem", &proc_root);
@@ -866,12 +861,7 @@
 		printk(KERN_ERR "IP2: failed to register callout driver (%d)\n", err);
 	} else
 	/* Register the IPL driver. */
-#ifdef	CONFIG_DEVFS_FS
-	if (( err = devfs_register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl )))
-#else
-	if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) )
-#endif
-	{
+	if ( ( err = register_chrdev ( IP2_IPL_MAJOR, pcIpl, &ip2_ipl ) ) ) {
 		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
 	} else
 	/* Register the read_procmem thing */
diff -Nru a/drivers/char/istallion.c b/drivers/char/istallion.c
--- a/drivers/char/istallion.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/char/istallion.c	Thu Aug  1 14:17:36 2002
@@ -869,7 +869,7 @@
 		return;
 	}
 	devfs_unregister (devfs_handle);
-	if ((i = devfs_unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
+	if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
 		printk("STALLION: failed to un-register serial memory device, "
 			"errno=%d\n", -i);
 	if (stli_tmpwritebuf != (char *) NULL)
@@ -5329,7 +5329,7 @@
  *	Set up a character driver for the shared memory region. We need this
  *	to down load the slave code image. Also it is a useful debugging tool.
  */
-	if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
+	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem))
 		printk(KERN_ERR "STALLION: failed to register serial memory "
 				"device\n");
 
diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c
--- a/drivers/char/lp.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/char/lp.c	Thu Aug  1 14:17:36 2002
@@ -903,7 +903,7 @@
 		lp_table[i].timeout = 10 * HZ;
 	}
 
-	if (devfs_register_chrdev (LP_MAJOR, "lp", &lp_fops)) {
+	if (register_chrdev (LP_MAJOR, "lp", &lp_fops)) {
 		printk ("lp: unable to get major %d\n", LP_MAJOR);
 		return -EIO;
 	}
@@ -965,7 +965,7 @@
 #endif
 
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev(LP_MAJOR, "lp");
+	unregister_chrdev(LP_MAJOR, "lp");
 	for (offset = 0; offset < LP_NO; offset++) {
 		if (lp_table[offset].dev == NULL)
 			continue;
diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/mem.c	Thu Aug  1 14:17:40 2002
@@ -651,7 +651,7 @@
 
 int __init chr_dev_init(void)
 {
-	if (devfs_register_chrdev(MEM_MAJOR,"mem",&memory_fops))
+	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
 		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
 	memory_devfs_register();
 	rand_initialize();
diff -Nru a/drivers/char/misc.c b/drivers/char/misc.c
--- a/drivers/char/misc.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/misc.c	Thu Aug  1 14:17:40 2002
@@ -281,7 +281,7 @@
 #ifdef CONFIG_I8K
 	i8k_init();
 #endif
-	if (devfs_register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
+	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
 		printk("unable to get major %d for misc devices\n",
 		       MISC_MAJOR);
 		return -EIO;
diff -Nru a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
--- a/drivers/char/n_r3964.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/char/n_r3964.c	Thu Aug  1 14:17:41 2002
@@ -13,6 +13,12 @@
  * L. Haag
  *
  * $Log: n_r3964.c,v $
+ * Revision 1.10  2001/03/18 13:02:24  dwmw2
+ * Fix timer usage, use spinlocks properly.
+ *
+ * Revision 1.9  2001/03/18 12:52:14  dwmw2
+ * Merge changes in 2.4.2
+ *
  * Revision 1.8  2000/03/23 14:14:54  dwmw2
  * Fix race in sleeping in r3964_read()
  *
@@ -110,8 +116,6 @@
 #define TRACE_Q(fmt, arg...) /**/
 #endif
 
-static void on_timer_1(void*);
-static void on_timer_2(void*);
 static void add_tx_queue(struct r3964_info *, struct r3964_block_header *);
 static void remove_from_tx_queue(struct r3964_info *pInfo, int error_code);
 static void put_char(struct r3964_info *pInfo, unsigned char ch);
@@ -120,7 +124,7 @@
 static void transmit_block(struct r3964_info *pInfo);
 static void receive_char(struct r3964_info *pInfo, const unsigned char c);
 static void receive_error(struct r3964_info *pInfo, const char flag);
-static void on_timeout(struct r3964_info *pInfo);
+static void on_timeout(unsigned long priv);
 static int enable_signals(struct r3964_info *pInfo, pid_t pid, int arg);
 static int read_telegram(struct r3964_info *pInfo, pid_t pid, unsigned char *buf);
 static void add_msg(struct r3964_client_info *pClient, int msg_id, int arg,
@@ -217,7 +221,7 @@
 {
    int status;
    
-   printk ("r3964: Philips r3964 Driver $Revision: 1.8 $\n");
+   printk ("r3964: Philips r3964 Driver $Revision: 1.10 $\n");
 
    /*
     * Register the tty line discipline
@@ -247,40 +251,11 @@
  * Protocol implementation routines
  *************************************************************/
 
-static void on_timer_1(void *arg)
-{
-   struct r3964_info *pInfo = (struct r3964_info *)arg;
-  
-   if(pInfo->count_down)
-   {
-      if(!--pInfo->count_down)
-      {
-         on_timeout(pInfo);
-      }
-   }
-   queue_task(&pInfo->bh_2, &tq_timer);
-}
-
-static void on_timer_2(void *arg)
-{
-   struct r3964_info *pInfo = (struct r3964_info *)arg;
-  
-   if(pInfo->count_down)
-   {
-      if(!--pInfo->count_down)
-      {
-         on_timeout(pInfo);
-      }
-   }
-   queue_task(&pInfo->bh_1, &tq_timer);
-}
-
 static void add_tx_queue(struct r3964_info *pInfo, struct r3964_block_header *pHeader)
 {
    unsigned long flags;
    
-   save_flags(flags);
-   cli();
+   spin_lock_irqsave(&pInfo->lock, flags);
 
    pHeader->next = NULL;
 
@@ -294,7 +269,7 @@
       pInfo->tx_last = pHeader;
    }
    
-   restore_flags(flags);
+   spin_unlock_irqrestore(&pInfo->lock, flags);
 
    TRACE_Q("add_tx_queue %x, length %d, tx_first = %x", 
           (int)pHeader, pHeader->length, (int)pInfo->tx_first );
@@ -337,8 +312,7 @@
       wake_up_interruptible (&pInfo->read_wait);
    }
 
-   save_flags(flags);
-   cli();
+   spin_lock_irqsave(&pInfo->lock, flags);
 
    pInfo->tx_first = pHeader->next;
    if(pInfo->tx_first==NULL)
@@ -346,7 +320,7 @@
       pInfo->tx_last = NULL;
    }
 
-   restore_flags(flags);
+   spin_unlock_irqrestore(&pInfo->lock, flags);
 
    kfree(pHeader);
    TRACE_M("remove_from_tx_queue - kfree %x",(int)pHeader);
@@ -359,8 +333,7 @@
 {
    unsigned long flags;
    
-   save_flags(flags);
-   cli();
+   spin_lock_irqsave(&pInfo->lock, flags);
 
    pHeader->next = NULL;
 
@@ -375,7 +348,7 @@
    }
    pInfo->blocks_in_rx_queue++;
    
-   restore_flags(flags);
+   spin_unlock_irqrestore(&pInfo->lock, flags);
 
    TRACE_Q("add_rx_queue: %x, length = %d, rx_first = %x, count = %d",
           (int)pHeader, pHeader->length,
@@ -396,8 +369,7 @@
    TRACE_Q("remove_from_rx_queue: %x, length %d",
           (int)pHeader, (int)pHeader->length );
 
-   save_flags(flags);
-   cli();
+   spin_lock_irqsave(&pInfo->lock, flags);
 
    if(pInfo->rx_first == pHeader)
    {
@@ -430,7 +402,7 @@
       }
    }
 
-   restore_flags(flags);
+   spin_unlock_irqrestore(&pInfo->lock, flags);
 
    kfree(pHeader);
    TRACE_M("remove_from_rx_queue - kfree %x",(int)pHeader);
@@ -471,17 +443,16 @@
    unsigned long flags;
    
 
-   save_flags(flags);
-   cli();
+   spin_lock_irqsave(&pInfo->lock, flags);
 
    if((pInfo->state == R3964_IDLE) && (pInfo->tx_first!=NULL))
    {
       pInfo->state = R3964_TX_REQUEST;
-      pInfo->count_down = R3964_TO_QVZ;
       pInfo->nRetry=0;
       pInfo->flags &= ~R3964_ERROR;
-      
-      restore_flags(flags);
+      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
+
+      spin_unlock_irqrestore(&pInfo->lock, flags);
 
       TRACE_PS("trigger_transmit - sent STX");
 
@@ -492,7 +463,7 @@
    }
    else
    {
-      restore_flags(flags);
+      spin_unlock_irqrestore(&pInfo->lock, flags);
    }
 }
 
@@ -506,8 +477,8 @@
       put_char(pInfo, STX);
       flush(pInfo);
       pInfo->state = R3964_TX_REQUEST;
-      pInfo->count_down = R3964_TO_QVZ;
       pInfo->nRetry++;
+      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
    }
    else
    {
@@ -566,7 +537,7 @@
          put_char(pInfo, pInfo->bcc);
       }
       pInfo->state = R3964_WAIT_FOR_TX_ACK;
-      pInfo->count_down = R3964_TO_QVZ;
+      mod_timer(&pInfo->tmr, jiffies + R3964_TO_QVZ);
    }
    flush(pInfo);
 }
@@ -601,8 +572,8 @@
       if(pInfo->nRetry<R3964_MAX_RETRIES)
       {
          pInfo->state=R3964_WAIT_FOR_RX_REPEAT;
-         pInfo->count_down = R3964_TO_RX_PANIC;
          pInfo->nRetry++;
+	 mod_timer(&pInfo->tmr, jiffies + R3964_TO_RX_PANIC);
       }
       else
       {
@@ -616,7 +587,7 @@
    /* received block; submit DLE: */
    put_char(pInfo, DLE);
    flush(pInfo);
-   pInfo->count_down=0;
+   del_timer_sync(&pInfo->tmr);
    TRACE_PS(" rx success: got %d chars", length);
 
    /* prepare struct r3964_block_header: */
@@ -701,7 +672,7 @@
             TRACE_PE("TRANSMITTING - got illegal char");
  
             pInfo->state = R3964_WAIT_ZVZ_BEFORE_TX_RETRY;
-            pInfo->count_down = R3964_TO_ZVZ;
+	    mod_timer(&pInfo->tmr, jiffies + R3964_TO_ZVZ);
          }
          break;
       case R3964_WAIT_FOR_TX_ACK:
@@ -728,7 +699,7 @@
             {
                TRACE_PE("IDLE - got STX but no space in rx_queue!");
                pInfo->state=R3964_WAIT_FOR_RX_BUF;
-               pInfo->count_down = R3964_TO_NO_BUF;
+	       mod_timer(&pInfo->tmr, R3964_TO_NO_BUF);
                break;
             }
 start_receiving:
@@ -738,8 +709,8 @@
             pInfo->last_rx = 0;
             pInfo->flags &= ~R3964_ERROR;
             pInfo->state=R3964_RECEIVING;
-            pInfo->count_down = R3964_TO_ZVZ;
-            pInfo->nRetry = 0;
+	    mod_timer(&pInfo->tmr, R3964_TO_ZVZ);
+	    pInfo->nRetry = 0;
             put_char(pInfo, DLE);
             flush(pInfo);
             pInfo->bcc = 0;
@@ -765,7 +736,7 @@
                if(pInfo->flags & R3964_BCC)
                {
                   pInfo->state = R3964_WAIT_FOR_BCC;
-                  pInfo->count_down = R3964_TO_ZVZ;
+		  mod_timer(&pInfo->tmr, R3964_TO_ZVZ);
                }
                else 
                {
@@ -777,7 +748,7 @@
                pInfo->last_rx = c;
 char_to_buf:
                pInfo->rx_buf[pInfo->rx_position++] = c;
-               pInfo->count_down = R3964_TO_ZVZ;
+	       mod_timer(&pInfo->tmr, R3964_TO_ZVZ);
             }
          }
         /* else: overflow-msg? BUF_SIZE>MTU; should not happen? */ 
@@ -818,8 +789,10 @@
     }
 }
 
-static void on_timeout(struct r3964_info *pInfo)
+static void on_timeout(unsigned long priv)
 {
+   struct r3964_info *pInfo = (void *)priv;
+
    switch(pInfo->state)
    {
       case R3964_TX_REQUEST:
@@ -926,6 +899,7 @@
             return -ENOMEM;
 
          TRACE_PS("add client %d to client list", pid);
+	 spin_lock_init(&pClient->lock);
          pClient->sig_flags=arg;
          pClient->pid = pid;
          pClient->next=pInfo->firstClient;
@@ -989,8 +963,7 @@
          return;
       }
 
-      save_flags(flags);
-      cli();
+      spin_lock_irqsave(&pClient->lock, flags);
 
       pMsg->msg_id = msg_id;
       pMsg->arg    = arg;
@@ -1014,7 +987,7 @@
       {
          pBlock->locks++;
       }
-      restore_flags(flags);
+      spin_unlock_irqrestore(&pClient->lock, flags);
    }
    else
    {
@@ -1049,8 +1022,7 @@
 
    if(pClient->first_msg)
    {
-      save_flags(flags);
-      cli();
+      spin_lock_irqsave(&pClient->lock, flags);
 
       pMsg = pClient->first_msg;
       pClient->first_msg = pMsg->next;
@@ -1065,7 +1037,7 @@
         remove_client_block(pInfo, pClient);
         pClient->next_block_to_read = pMsg->block;
       }
-      restore_flags(flags);
+      spin_unlock_irqrestore(&pClient->lock, flags);
    }
    return pMsg;
 }
@@ -1137,6 +1109,7 @@
       return -ENOMEM;
    }
 
+   spin_lock_init(&pInfo->lock);
    pInfo->tty = tty;
    init_waitqueue_head (&pInfo->read_wait);
    pInfo->priority = R3964_MASTER;
@@ -1149,26 +1122,13 @@
    pInfo->firstClient=NULL;
    pInfo->state=R3964_IDLE;
    pInfo->flags = R3964_DEBUG;
-   pInfo->count_down = 0;
    pInfo->nRetry = 0;
    
    tty->disc_data = pInfo;
 
-   /*
-    * Add 'on_timer' to timer task queue
-    * (will be called from timer bh)
-    */
-   INIT_LIST_HEAD(&pInfo->bh_1.list);
-   pInfo->bh_1.sync = 0;
-   pInfo->bh_1.routine = &on_timer_1;
-   pInfo->bh_1.data = pInfo;
-   
-   INIT_LIST_HEAD(&pInfo->bh_2.list);
-   pInfo->bh_2.sync = 0;
-   pInfo->bh_2.routine = &on_timer_2;
-   pInfo->bh_2.data = pInfo;
-
-   queue_task(&pInfo->bh_1, &tq_timer);
+   INIT_LIST_HEAD(&pInfo->tmr.list);
+   pInfo->tmr.data = (unsigned long)pInfo;
+   pInfo->tmr.function = on_timeout;
 
    return 0;
 }
@@ -1187,12 +1147,7 @@
      * Make sure that our task queue isn't activated.  If it
      * is, take it out of the linked list.
      */
-    spin_lock_irqsave(&tqueue_lock, flags);
-    if (pInfo->bh_1.sync)
-    	list_del(&pInfo->bh_1.list);
-    if (pInfo->bh_2.sync)
-    	list_del(&pInfo->bh_2.list);
-    spin_unlock_irqrestore(&tqueue_lock, flags);
+    del_timer_sync(&pInfo->tmr);
 
    /* Remove client-structs and message queues: */
     pClient=pInfo->firstClient;
@@ -1213,11 +1168,10 @@
        pClient=pNext;
     }
     /* Remove jobs from tx_queue: */
-	save_flags(flags);
-        cli();
+        spin_lock_irqsave(&pInfo->lock, flags);
 	pHeader=pInfo->tx_first;
 	pInfo->tx_first=pInfo->tx_last=NULL;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&pInfo->lock, flags);
 	
     while(pHeader)
 	{
@@ -1430,10 +1384,9 @@
    if(pClient)
      {
        poll_wait(file, &pInfo->read_wait, wait);
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&pInfo->lock, flags);
        pMsg=pClient->first_msg;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&pInfo->lock, flags);
        if(pMsg)
 	   result |= POLLIN | POLLRDNORM;
      }
diff -Nru a/drivers/char/nvram.c b/drivers/char/nvram.c
--- a/drivers/char/nvram.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/nvram.c	Thu Aug  1 14:17:40 2002
@@ -38,12 +38,12 @@
 #include <linux/smp_lock.h>
 
 #define PC		1
-#define ATARI	2
+#define ATARI		2
 
 /* select machine configuration */
 #if defined(CONFIG_ATARI)
 #define MACH ATARI
-#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */
+#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)  /* and others?? */
 #define MACH PC
 #else
 #error Cannot build nvram driver for this machine configuration.
@@ -52,12 +52,12 @@
 #if MACH == PC
 
 /* RTC in a PC */
-#define CHECK_DRIVER_INIT() 1
+#define CHECK_DRIVER_INIT()	1
 
 /* On PCs, the checksum is built only over bytes 2..31 */
 #define PC_CKS_RANGE_START	2
 #define PC_CKS_RANGE_END	31
-#define PC_CKS_LOC			32
+#define PC_CKS_LOC		32
 
 #define	mach_check_checksum	pc_check_checksum
 #define	mach_set_checksum	pc_set_checksum
@@ -70,14 +70,14 @@
 /* Special parameters for RTC in Atari machines */
 #include <asm/atarihw.h>
 #include <asm/atariints.h>
-#define RTC_PORT(x)			(TT_RTC_BAS + 2*(x))
-#define CHECK_DRIVER_INIT() (MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))
+#define RTC_PORT(x)		(TT_RTC_BAS + 2*(x))
+#define CHECK_DRIVER_INIT()	(MACH_IS_ATARI && ATARIHW_PRESENT(TT_CLK))
 
 /* On Ataris, the checksum is over all bytes except the checksum bytes
  * themselves; these are at the very end */
 #define ATARI_CKS_RANGE_START	0
-#define ATARI_CKS_RANGE_END		47
-#define ATARI_CKS_LOC			48
+#define ATARI_CKS_RANGE_END	47
+#define ATARI_CKS_LOC		48
 
 #define	mach_check_checksum	atari_check_checksum
 #define	mach_set_checksum	atari_set_checksum
@@ -109,46 +109,50 @@
 
 static int nvram_open_cnt;	/* #times opened */
 static int nvram_open_mode;	/* special open modes */
-static spinlock_t nvram_open_lock = SPIN_LOCK_UNLOCKED;
-                               /* guards nvram_open_cnt and
-                                         nvram_open_mode */
-#define	NVRAM_WRITE		1		/* opened for writing (exclusive) */
-#define	NVRAM_EXCL		2		/* opened with O_EXCL */
+static spinlock_t nvram_open_lock = SPIN_LOCK_UNLOCKED; /* guards 
+							 * nvram_open_cnt and
+							 * nvram_open_mode */
+#define	NVRAM_WRITE		1	/* opened for writing (exclusive) */
+#define	NVRAM_EXCL		2	/* opened with O_EXCL */
+
+#define	RTC_FIRST_BYTE		14	/* RTC register number of first
+					 * NVRAM byte */
+#define	NVRAM_BYTES		128-RTC_FIRST_BYTE /* number of NVRAM bytes */
 
-#define	RTC_FIRST_BYTE		14	/* RTC register number of first NVRAM byte */
-#define	NVRAM_BYTES			128-RTC_FIRST_BYTE	/* number of NVRAM bytes */
+static int mach_check_checksum(void);
+static void mach_set_checksum(void);
 
-
-static int mach_check_checksum( void );
-static void mach_set_checksum( void );
 #ifdef CONFIG_PROC_FS
-static int mach_proc_infos( unsigned char *contents, char *buffer, int *len,
-							off_t *begin, off_t offset, int size );
+static int mach_proc_infos(unsigned char *contents, char *buffer, int *len,
+    off_t *begin, off_t offset, int size);
 #endif
 
-
 /*
  * These are the internal NVRAM access functions, which do NOT disable
  * interrupts and do not check the checksum. Both tasks are left to higher
  * level function, so they need to be done only once per syscall.
  */
 
-static __inline__ unsigned char nvram_read_int( int i )
+static __inline__ unsigned char
+nvram_read_int(int i)
 {
-	return( CMOS_READ( RTC_FIRST_BYTE+i ) );
+	return CMOS_READ(RTC_FIRST_BYTE + i);
 }
 
-static __inline__ void nvram_write_int( unsigned char c, int i )
+static __inline__ void
+nvram_write_int(unsigned char c, int i)
 {
-	CMOS_WRITE( c, RTC_FIRST_BYTE+i );
+	CMOS_WRITE(c, RTC_FIRST_BYTE + i);
 }
 
-static __inline__ int nvram_check_checksum_int( void )
+static __inline__ int
+nvram_check_checksum_int(void)
 {
-	return( mach_check_checksum() );
+	return mach_check_checksum();
 }
 
-static __inline__ void nvram_set_checksum_int( void )
+static __inline__ void
+nvram_set_checksum_int(void)
 {
 	mach_set_checksum();
 }
@@ -166,178 +170,183 @@
  * module), so they access config information themselves.
  */
 
-unsigned char nvram_read_byte( int i )
+unsigned char
+nvram_read_byte(int i)
 {
 	unsigned long flags;
 	unsigned char c;
 
-	spin_lock_irqsave (&rtc_lock, flags);
-	c = nvram_read_int( i );
-	spin_unlock_irqrestore (&rtc_lock, flags);
-	return( c );
+	spin_lock_irqsave(&rtc_lock, flags);
+	c = nvram_read_int(i);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return c;
 }
 
 /* This races nicely with trying to read with checksum checking (nvram_read) */
-void nvram_write_byte( unsigned char c, int i )
+void
+nvram_write_byte(unsigned char c, int i)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave (&rtc_lock, flags);
-	nvram_write_int( c, i );
-	spin_unlock_irqrestore (&rtc_lock, flags);
+	spin_lock_irqsave(&rtc_lock, flags);
+	nvram_write_int(c, i);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 }
 
-int nvram_check_checksum( void )
+int
+nvram_check_checksum(void)
 {
 	unsigned long flags;
 	int rv;
 
-	spin_lock_irqsave (&rtc_lock, flags);
+	spin_lock_irqsave(&rtc_lock, flags);
 	rv = nvram_check_checksum_int();
-	spin_unlock_irqrestore (&rtc_lock, flags);
-	return( rv );
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return rv;
 }
 
-void nvram_set_checksum( void )
+void
+nvram_set_checksum(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave (&rtc_lock, flags);
+	spin_lock_irqsave(&rtc_lock, flags);
 	nvram_set_checksum_int();
-	spin_unlock_irqrestore (&rtc_lock, flags);
+	spin_unlock_irqrestore(&rtc_lock, flags);
 }
 
 #endif /* MACH == ATARI */
 
-
 /*
  * The are the file operation function for user access to /dev/nvram
  */
 
-static long long nvram_llseek(struct file *file,loff_t offset, int origin )
+static long long
+nvram_llseek(struct file *file, loff_t offset, int origin)
 {
 	lock_kernel();
-	switch( origin ) {
-	  case 0:
+	switch (origin) {
+	case 0:
 		/* nothing to do */
 		break;
-	  case 1:
+	case 1:
 		offset += file->f_pos;
 		break;
-	  case 2:
+	case 2:
 		offset += NVRAM_BYTES;
 		break;
 	}
 	unlock_kernel();
-	return( (offset >= 0) ? (file->f_pos = offset) : -EINVAL );
+	return (offset >= 0) ? (file->f_pos = offset) : -EINVAL;
 }
 
-static ssize_t nvram_read(struct file * file,
-	char * buf, size_t count, loff_t *ppos )
+static ssize_t
+nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-	char contents [NVRAM_BYTES];
+	char contents[NVRAM_BYTES];
 	unsigned i = *ppos;
 	char *tmp;
 
-	spin_lock_irq (&rtc_lock);
-	
+	spin_lock_irq(&rtc_lock);
+
 	if (!nvram_check_checksum_int())
 		goto checksum_err;
 
 	for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
 		*tmp = nvram_read_int(i);
 
-	spin_unlock_irq (&rtc_lock);
+	spin_unlock_irq(&rtc_lock);
 
-	if (copy_to_user (buf, contents, tmp - contents))
+	if (copy_to_user(buf, contents, tmp - contents))
 		return -EFAULT;
 
 	*ppos = i;
 
-	return (tmp - contents);
+	return tmp - contents;
 
-checksum_err:
-	spin_unlock_irq (&rtc_lock);
+      checksum_err:
+	spin_unlock_irq(&rtc_lock);
 	return -EIO;
 }
 
-static ssize_t nvram_write(struct file * file,
-		const char * buf, size_t count, loff_t *ppos )
+static ssize_t
+nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-	char contents [NVRAM_BYTES];
+	char contents[NVRAM_BYTES];
 	unsigned i = *ppos;
-	char * tmp;
+	char *tmp;
 
-	if (copy_from_user (contents, buf, (NVRAM_BYTES - i) < count ?
-						(NVRAM_BYTES - i) : count))
+	if (copy_from_user(contents, buf, (NVRAM_BYTES - i) < count ?
+	    (NVRAM_BYTES - i) : count))
 		return -EFAULT;
 
-	spin_lock_irq (&rtc_lock);
+	spin_lock_irq(&rtc_lock);
 
 	if (!nvram_check_checksum_int())
 		goto checksum_err;
 
 	for (tmp = contents; count-- > 0 && i < NVRAM_BYTES; ++i, ++tmp)
-		nvram_write_int (*tmp, i);
+		nvram_write_int(*tmp, i);
 
 	nvram_set_checksum_int();
 
-	spin_unlock_irq (&rtc_lock);
+	spin_unlock_irq(&rtc_lock);
 
 	*ppos = i;
 
-	return (tmp - contents);
+	return tmp - contents;
 
-checksum_err:
-	spin_unlock_irq (&rtc_lock);
+      checksum_err:
+	spin_unlock_irq(&rtc_lock);
 	return -EIO;
 }
 
-static int nvram_ioctl( struct inode *inode, struct file *file,
-						unsigned int cmd, unsigned long arg )
+static int
+nvram_ioctl(struct inode *inode, struct file *file,
+    unsigned int cmd, unsigned long arg)
 {
 	int i;
-	
-	switch( cmd ) {
 
-	  case NVRAM_INIT:			/* initialize NVRAM contents and checksum */
+	switch (cmd) {
+
+	case NVRAM_INIT:	/* initialize NVRAM contents and checksum */
 		if (!capable(CAP_SYS_ADMIN))
-			return( -EACCES );
+			return -EACCES;
 
-		spin_lock_irq (&rtc_lock);
+		spin_lock_irq(&rtc_lock);
 
-		for( i = 0; i < NVRAM_BYTES; ++i )
-			nvram_write_int( 0, i );
+		for (i = 0; i < NVRAM_BYTES; ++i)
+			nvram_write_int(0, i);
 		nvram_set_checksum_int();
-		
-		spin_unlock_irq (&rtc_lock);
-		return( 0 );
-	  
-	  case NVRAM_SETCKS:		/* just set checksum, contents unchanged
-								 * (maybe useful after checksum garbaged
-								 * somehow...) */
+
+		spin_unlock_irq(&rtc_lock);
+		return 0;
+
+	case NVRAM_SETCKS:	/* just set checksum, contents unchanged
+				 * (maybe useful after checksum garbaged
+				 * somehow...) */
 		if (!capable(CAP_SYS_ADMIN))
-			return( -EACCES );
+			return -EACCES;
 
-		spin_lock_irq (&rtc_lock);
+		spin_lock_irq(&rtc_lock);
 		nvram_set_checksum_int();
-		spin_unlock_irq (&rtc_lock);
-		return( 0 );
+		spin_unlock_irq(&rtc_lock);
+		return 0;
 
-	  default:
-		return( -ENOTTY );
+	default:
+		return -ENOTTY;
 	}
 }
 
-static int nvram_open( struct inode *inode, struct file *file )
+static int
+nvram_open(struct inode *inode, struct file *file)
 {
-	spin_lock( &nvram_open_lock );
+	spin_lock(&nvram_open_lock);
 	if ((nvram_open_cnt && (file->f_flags & O_EXCL)) ||
-		(nvram_open_mode & NVRAM_EXCL) ||
-		((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE)))
-	{	
-		spin_unlock( &nvram_open_lock );
-		return( -EBUSY );
+	    (nvram_open_mode & NVRAM_EXCL) ||
+	    ((file->f_mode & 2) && (nvram_open_mode & NVRAM_WRITE))) {
+		spin_unlock(&nvram_open_lock);
+		return -EBUSY;
 	}
 
 	if (file->f_flags & O_EXCL)
@@ -345,60 +354,65 @@
 	if (file->f_mode & 2)
 		nvram_open_mode |= NVRAM_WRITE;
 	nvram_open_cnt++;
-	spin_unlock( &nvram_open_lock );
-	return( 0 );
+	spin_unlock(&nvram_open_lock);
+	return 0;
 }
 
-static int nvram_release( struct inode *inode, struct file *file )
+static int
+nvram_release(struct inode *inode, struct file *file)
 {
-	spin_lock( &nvram_open_lock );
+	spin_lock(&nvram_open_lock);
 	nvram_open_cnt--;
 	if (file->f_flags & O_EXCL)
 		nvram_open_mode &= ~NVRAM_EXCL;
 	if (file->f_mode & 2)
 		nvram_open_mode &= ~NVRAM_WRITE;
-	spin_unlock( &nvram_open_lock );
-	return( 0 );
+	spin_unlock(&nvram_open_lock);
+	return 0;
 }
 
-
 #ifndef CONFIG_PROC_FS
-static int nvram_read_proc( char *buffer, char **start, off_t offset,
-			    int size, int *eof, void *data) { return 0; }
+static int
+nvram_read_proc(char *buffer, char **start, off_t offset,
+    int size, int *eof, void *data)
+{
+	return 0;
+}
 #else
 
-static int nvram_read_proc( char *buffer, char **start, off_t offset,
-							int size, int *eof, void *data )
+static int
+nvram_read_proc(char *buffer, char **start, off_t offset,
+    int size, int *eof, void *data)
 {
 	unsigned char contents[NVRAM_BYTES];
-    int i, len = 0;
-    off_t begin = 0;
+	int i, len = 0;
+	off_t begin = 0;
+
+	spin_lock_irq(&rtc_lock);
+	for (i = 0; i < NVRAM_BYTES; ++i)
+		contents[i] = nvram_read_int(i);
+	spin_unlock_irq(&rtc_lock);
+
+	*eof = mach_proc_infos(contents, buffer, &len, &begin, offset, size);
+
+	if (offset >= begin + len)
+		return 0;
+	*start = buffer + (offset - begin);
+	return (size < begin + len - offset) ? size : begin + len - offset;
 
-	spin_lock_irq (&rtc_lock);
-	for( i = 0; i < NVRAM_BYTES; ++i )
-		contents[i] = nvram_read_int( i );
-	spin_unlock_irq (&rtc_lock);
-	
-	*eof = mach_proc_infos( contents, buffer, &len, &begin, offset, size );
-
-    if (offset >= begin + len)
-		return( 0 );
-    *start = buffer + (offset - begin);
-    return( size < begin + len - offset ? size : begin + len - offset );
-	
 }
 
 /* This macro frees the machine specific function from bounds checking and
  * this like that... */
-#define	PRINT_PROC(fmt,args...)							\
-	do {												\
-		*len += sprintf( buffer+*len, fmt, ##args );	\
-		if (*begin + *len > offset + size)				\
-			return( 0 );								\
-		if (*begin + *len < offset) {					\
-			*begin += *len;								\
-			*len = 0;									\
-		}												\
+#define	PRINT_PROC(fmt,args...)					\
+	do {							\
+		*len += sprintf(buffer+*len, fmt, ##args);	\
+		if (*begin + *len > offset + size)		\
+			return 0;				\
+		if (*begin + *len < offset) {			\
+			*begin += *len;				\
+			*len = 0;				\
+		}						\
 	} while(0)
 
 #endif /* CONFIG_PROC_FS */
@@ -419,72 +433,74 @@
 	&nvram_fops
 };
 
-
-static int __init nvram_init(void)
+static int __init
+nvram_init(void)
 {
 	int ret;
 
 	/* First test whether the driver should init at all */
 	if (!CHECK_DRIVER_INIT())
-	    return( -ENXIO );
+		return -ENXIO;
 
-	ret = misc_register( &nvram_dev );
+	ret = misc_register(&nvram_dev);
 	if (ret) {
-		printk(KERN_ERR "nvram: can't misc_register on minor=%d\n", NVRAM_MINOR);
+		printk(KERN_ERR "nvram: can't misc_register on minor=%d\n",
+		    NVRAM_MINOR);
 		goto out;
 	}
-	if (!create_proc_read_entry("driver/nvram",0,0,nvram_read_proc,NULL)) {
+	if (!create_proc_read_entry("driver/nvram", 0, 0, nvram_read_proc,
+		NULL)) {
 		printk(KERN_ERR "nvram: can't create /proc/driver/nvram\n");
 		ret = -ENOMEM;
 		goto outmisc;
 	}
 	ret = 0;
 	printk(KERN_INFO "Non-volatile memory driver v" NVRAM_VERSION "\n");
-out:
-	return( ret );
-outmisc:
-	misc_deregister( &nvram_dev );
+      out:
+	return ret;
+      outmisc:
+	misc_deregister(&nvram_dev);
 	goto out;
 }
 
-static void __exit nvram_cleanup_module (void)
+static void __exit
+nvram_cleanup_module(void)
 {
-	remove_proc_entry( "driver/nvram", 0 );
-	misc_deregister( &nvram_dev );
+	remove_proc_entry("driver/nvram", 0);
+	misc_deregister(&nvram_dev);
 }
 
 module_init(nvram_init);
 module_exit(nvram_cleanup_module);
 
-
 /*
  * Machine specific functions
  */
 
-
 #if MACH == PC
 
-static int pc_check_checksum( void )
+static int
+pc_check_checksum(void)
 {
 	int i;
 	unsigned short sum = 0;
-	
-	for( i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i )
-		sum += nvram_read_int( i );
-	return( (sum & 0xffff) ==
-			((nvram_read_int(PC_CKS_LOC) << 8) |
-			 nvram_read_int(PC_CKS_LOC+1)) );
+
+	for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
+		sum += nvram_read_int(i);
+	return ((sum & 0xffff) ==
+	    ((nvram_read_int(PC_CKS_LOC)<<8) | nvram_read_int(PC_CKS_LOC+1)));
 }
 
-static void pc_set_checksum( void )
+static void
+pc_set_checksum(void)
 {
 	int i;
 	unsigned short sum = 0;
-	
-	for( i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i )
-		sum += nvram_read_int( i );
-	nvram_write_int( sum >> 8, PC_CKS_LOC );
-	nvram_write_int( sum & 0xff, PC_CKS_LOC+1 );
+
+	for (i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; ++i)
+		sum += nvram_read_int(i);
+	nvram_write_int(sum >> 8, PC_CKS_LOC);
+	nvram_write_int(sum & 0xff, PC_CKS_LOC + 1);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -501,69 +517,67 @@
 	"monochrome",
 };
 
-static int pc_proc_infos( unsigned char *nvram, char *buffer, int *len,
-						  off_t *begin, off_t offset, int size )
+static int
+pc_proc_infos(unsigned char *nvram, char *buffer, int *len,
+    off_t *begin, off_t offset, int size)
 {
 	int checksum;
 	int type;
 
-	spin_lock_irq (&rtc_lock);
+	spin_lock_irq(&rtc_lock);
 	checksum = nvram_check_checksum_int();
-	spin_unlock_irq (&rtc_lock);
+	spin_unlock_irq(&rtc_lock);
 
-	PRINT_PROC( "Checksum status: %svalid\n", checksum ? "" : "not " );
+	PRINT_PROC("Checksum status: %svalid\n", checksum ? "" : "not ");
 
-	PRINT_PROC( "# floppies     : %d\n",
-				(nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0 );
-	PRINT_PROC( "Floppy 0 type  : " );
+	PRINT_PROC("# floppies     : %d\n",
+	    (nvram[6] & 1) ? (nvram[6] >> 6) + 1 : 0);
+	PRINT_PROC("Floppy 0 type  : ");
 	type = nvram[2] >> 4;
-	if (type < sizeof(floppy_types)/sizeof(*floppy_types))
-		PRINT_PROC( "%s\n", floppy_types[type] );
+	if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+		PRINT_PROC("%s\n", floppy_types[type]);
 	else
-		PRINT_PROC( "%d (unknown)\n", type );
-	PRINT_PROC( "Floppy 1 type  : " );
+		PRINT_PROC("%d (unknown)\n", type);
+	PRINT_PROC("Floppy 1 type  : ");
 	type = nvram[2] & 0x0f;
-	if (type < sizeof(floppy_types)/sizeof(*floppy_types))
-		PRINT_PROC( "%s\n", floppy_types[type] );
+	if (type < sizeof (floppy_types) / sizeof (*floppy_types))
+		PRINT_PROC("%s\n", floppy_types[type]);
 	else
-		PRINT_PROC( "%d (unknown)\n", type );
+		PRINT_PROC("%d (unknown)\n", type);
 
-	PRINT_PROC( "HD 0 type      : " );
+	PRINT_PROC("HD 0 type      : ");
 	type = nvram[4] >> 4;
 	if (type)
-		PRINT_PROC( "%02x\n", type == 0x0f ? nvram[11] : type );
+		PRINT_PROC("%02x\n", type == 0x0f ? nvram[11] : type);
 	else
-		PRINT_PROC( "none\n" );
+		PRINT_PROC("none\n");
 
-	PRINT_PROC( "HD 1 type      : " );
+	PRINT_PROC("HD 1 type      : ");
 	type = nvram[4] & 0x0f;
 	if (type)
-		PRINT_PROC( "%02x\n", type == 0x0f ? nvram[12] : type );
+		PRINT_PROC("%02x\n", type == 0x0f ? nvram[12] : type);
 	else
-		PRINT_PROC( "none\n" );
+		PRINT_PROC("none\n");
+
+	PRINT_PROC("HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
+	    nvram[18] | (nvram[19] << 8),
+	    nvram[20], nvram[25],
+	    nvram[21] | (nvram[22] << 8), nvram[23] | (nvram[24] << 8));
+	PRINT_PROC("HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
+	    nvram[39] | (nvram[40] << 8),
+	    nvram[41], nvram[46],
+	    nvram[42] | (nvram[43] << 8), nvram[44] | (nvram[45] << 8));
+
+	PRINT_PROC("DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8));
+	PRINT_PROC("Extended memory: %d kB (configured), %d kB (tested)\n",
+	    nvram[9] | (nvram[10] << 8), nvram[34] | (nvram[35] << 8));
 
-	PRINT_PROC( "HD type 48 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
-				nvram[18] | (nvram[19] << 8),
-				nvram[20], nvram[25],
-				nvram[21] | (nvram[22] << 8),
-				nvram[23] | (nvram[24] << 8) );
-	PRINT_PROC( "HD type 49 data: %d/%d/%d C/H/S, precomp %d, lz %d\n",
-				nvram[39] | (nvram[40] << 8),
-				nvram[41], nvram[46],
-				nvram[42] | (nvram[43] << 8),
-				nvram[44] | (nvram[45] << 8) );
-
-	PRINT_PROC( "DOS base memory: %d kB\n", nvram[7] | (nvram[8] << 8) );
-	PRINT_PROC( "Extended memory: %d kB (configured), %d kB (tested)\n",
-				nvram[9] | (nvram[10] << 8),
-				nvram[34] | (nvram[35] << 8) );
-
-	PRINT_PROC( "Gfx adapter    : %s\n", gfx_types[ (nvram[6] >> 4)&3 ] );
-
-	PRINT_PROC( "FPU            : %sinstalled\n",
-				(nvram[6] & 2) ? "" : "not " );
-	
-	return( 1 );
+	PRINT_PROC("Gfx adapter    : %s\n", gfx_types[(nvram[6] >> 4) & 3]);
+
+	PRINT_PROC("FPU            : %sinstalled\n",
+	    (nvram[6] & 2) ? "" : "not ");
+
+	return 1;
 }
 #endif
 
@@ -571,26 +585,28 @@
 
 #if MACH == ATARI
 
-static int atari_check_checksum( void )
+static int
+atari_check_checksum(void)
 {
 	int i;
 	unsigned char sum = 0;
-	
-	for( i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i )
-		sum += nvram_read_int( i );
-	return( nvram_read_int( ATARI_CKS_LOC ) == (~sum & 0xff) &&
-			nvram_read_int( ATARI_CKS_LOC+1 ) == (sum & 0xff) );
+
+	for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
+		sum += nvram_read_int(i);
+	return (nvram_read_int(ATARI_CKS_LOC) == (~sum & 0xff) &&
+	    nvram_read_int(ATARI_CKS_LOC + 1) == (sum & 0xff));
 }
 
-static void atari_set_checksum( void )
+static void
+atari_set_checksum(void)
 {
 	int i;
 	unsigned char sum = 0;
-	
-	for( i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i )
-		sum += nvram_read_int( i );
-	nvram_write_int( ~sum, ATARI_CKS_LOC );
-	nvram_write_int( sum, ATARI_CKS_LOC+1 );
+
+	for (i = ATARI_CKS_RANGE_START; i <= ATARI_CKS_RANGE_END; ++i)
+		sum += nvram_read_int(i);
+	nvram_write_int(~sum, ATARI_CKS_LOC);
+	nvram_write_int(sum, ATARI_CKS_LOC + 1);
 }
 
 #ifdef CONFIG_PROC_FS
@@ -635,81 +651,74 @@
 
 #define fieldsize(a)	(sizeof(a)/sizeof(*a))
 
-static int atari_proc_infos( unsigned char *nvram, char *buffer, int *len,
-			    off_t *begin, off_t offset, int size )
+static int
+atari_proc_infos(unsigned char *nvram, char *buffer, int *len,
+    off_t *begin, off_t offset, int size)
 {
 	int checksum = nvram_check_checksum();
 	int i;
 	unsigned vmode;
-	
-	PRINT_PROC( "Checksum status  : %svalid\n", checksum ? "" : "not " );
 
-	PRINT_PROC( "Boot preference  : " );
-	for( i = fieldsize(boot_prefs)-1; i >= 0; --i ) {
+	PRINT_PROC("Checksum status  : %svalid\n", checksum ? "" : "not ");
+
+	PRINT_PROC("Boot preference  : ");
+	for (i = fieldsize(boot_prefs) - 1; i >= 0; --i) {
 		if (nvram[1] == boot_prefs[i].val) {
-			PRINT_PROC( "%s\n", boot_prefs[i].name );
+			PRINT_PROC("%s\n", boot_prefs[i].name);
 			break;
 		}
 	}
 	if (i < 0)
-		PRINT_PROC( "0x%02x (undefined)\n", nvram[1] );
+		PRINT_PROC("0x%02x (undefined)\n", nvram[1]);
 
-	PRINT_PROC( "SCSI arbitration : %s\n", (nvram[16] & 0x80) ? "on" : "off" );
-	PRINT_PROC( "SCSI host ID     : " );
+	PRINT_PROC("SCSI arbitration : %s\n",
+	    (nvram[16] & 0x80) ? "on" : "off");
+	PRINT_PROC("SCSI host ID     : ");
 	if (nvram[16] & 0x80)
-		PRINT_PROC( "%d\n", nvram[16] & 7 );
+		PRINT_PROC("%d\n", nvram[16] & 7);
 	else
-		PRINT_PROC( "n/a\n" );
+		PRINT_PROC("n/a\n");
 
 	/* the following entries are defined only for the Falcon */
 	if ((atari_mch_cookie >> 16) != ATARI_MCH_FALCON)
 		return 1;
 
-	PRINT_PROC( "OS language      : " );
+	PRINT_PROC("OS language      : ");
 	if (nvram[6] < fieldsize(languages))
-		PRINT_PROC( "%s\n", languages[nvram[6]] );
+		PRINT_PROC("%s\n", languages[nvram[6]]);
 	else
-		PRINT_PROC( "%u (undefined)\n", nvram[6] );
-	PRINT_PROC( "Keyboard language: " );
+		PRINT_PROC("%u (undefined)\n", nvram[6]);
+	PRINT_PROC("Keyboard language: ");
 	if (nvram[7] < fieldsize(languages))
-		PRINT_PROC( "%s\n", languages[nvram[7]] );
+		PRINT_PROC("%s\n", languages[nvram[7]]);
 	else
-		PRINT_PROC( "%u (undefined)\n", nvram[7] );
-	PRINT_PROC( "Date format      : " );
-	PRINT_PROC( dateformat[nvram[8]&7],
-				nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/' );
-	PRINT_PROC( ", %dh clock\n", nvram[8] & 16 ? 24 : 12 );
-	PRINT_PROC( "Boot delay       : " );
+		PRINT_PROC("%u (undefined)\n", nvram[7]);
+	PRINT_PROC("Date format      : ");
+	PRINT_PROC(dateformat[nvram[8] & 7],
+	    nvram[9] ? nvram[9] : '/', nvram[9] ? nvram[9] : '/');
+	PRINT_PROC(", %dh clock\n", nvram[8] & 16 ? 24 : 12);
+	PRINT_PROC("Boot delay       : ");
 	if (nvram[10] == 0)
-		PRINT_PROC( "default" );
+		PRINT_PROC("default");
 	else
-		PRINT_PROC( "%ds%s\n", nvram[10],
-					nvram[10] < 8 ? ", no memory test" : "" );
+		PRINT_PROC("%ds%s\n", nvram[10],
+		    nvram[10] < 8 ? ", no memory test" : "");
 
 	vmode = (nvram[14] << 8) || nvram[15];
-	PRINT_PROC( "Video mode       : %s colors, %d columns, %s %s monitor\n",
-				colors[vmode & 7],
-				vmode & 8 ? 80 : 40,
-				vmode & 16 ? "VGA" : "TV",
-				vmode & 32 ? "PAL" : "NTSC" );
-	PRINT_PROC( "                   %soverscan, compat. mode %s%s\n",
-				vmode & 64 ? "" : "no ",
-				vmode & 128 ? "on" : "off",
-				vmode & 256 ?
-				  (vmode & 16 ? ", line doubling" : ", half screen") : "" );
-		
-	return( 1 );
+	PRINT_PROC("Video mode       : %s colors, %d columns, %s %s monitor\n",
+	    colors[vmode & 7],
+	    vmode & 8 ? 80 : 40,
+	    vmode & 16 ? "VGA" : "TV", vmode & 32 ? "PAL" : "NTSC");
+	PRINT_PROC("                   %soverscan, compat. mode %s%s\n",
+	    vmode & 64 ? "" : "no ",
+	    vmode & 128 ? "on" : "off",
+	    vmode & 256 ?
+	    (vmode & 16 ? ", line doubling" : ", half screen") : "");
+
+	return 1;
 }
 #endif
 
 #endif /* MACH == ATARI */
 
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 4
- * End:
- */
-
diff -Nru a/drivers/char/ppdev.c b/drivers/char/ppdev.c
--- a/drivers/char/ppdev.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/ppdev.c	Thu Aug  1 14:17:40 2002
@@ -749,7 +749,7 @@
 
 static int __init ppdev_init (void)
 {
-	if (devfs_register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) {
+	if (register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) {
 		printk (KERN_WARNING CHRDEV ": unable to get major %d\n",
 			PP_MAJOR);
 		return -EIO;
@@ -768,7 +768,7 @@
 {
 	/* Clean up all parport stuff */
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev (PP_MAJOR, CHRDEV);
+	unregister_chrdev (PP_MAJOR, CHRDEV);
 }
 
 module_init(ppdev_init);
diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/char/raw.c	Thu Aug  1 14:17:36 2002
@@ -12,165 +12,106 @@
 #include <linux/fs.h>
 #include <linux/major.h>
 #include <linux/blkdev.h>
+#include <linux/module.h>
 #include <linux/raw.h>
 #include <linux/capability.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
 
-#define dprintk(x...) 
+#include <asm/uaccess.h>
 
-typedef struct raw_device_data_s {
+struct raw_device_data {
 	struct block_device *binding;
-	int inuse, sector_size, sector_bits;
-	struct semaphore mutex;
-} raw_device_data_t;
-
-static raw_device_data_t raw_devices[256];
-
-static ssize_t rw_raw_dev(int rw, struct file *, char *, size_t, loff_t *);
-
-ssize_t	raw_read(struct file *, char *, size_t, loff_t *);
-ssize_t	raw_write(struct file *, const char *, size_t, loff_t *);
-int	raw_open(struct inode *, struct file *);
-int	raw_release(struct inode *, struct file *);
-int	raw_ctl_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-int	raw_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
-
-
-static struct file_operations raw_fops = {
-	read:		raw_read,
-	write:		raw_write,
-	open:		raw_open,
-	release:	raw_release,
-	ioctl:		raw_ioctl,
-};
-
-static struct file_operations raw_ctl_fops = {
-	ioctl:		raw_ctl_ioctl,
-	open:		raw_open,
+	int inuse;
 };
 
-static int __init raw_init(void)
-{
-	int i;
-	register_chrdev(RAW_MAJOR, "raw", &raw_fops);
+static struct raw_device_data raw_devices[256];
+static DECLARE_MUTEX(raw_mutex);
+static struct file_operations raw_ctl_fops;
 
-	for (i = 0; i < 256; i++)
-		init_MUTEX(&raw_devices[i].mutex);
-
-	return 0;
-}
-
-__initcall(raw_init);
-
-/* 
+/*
  * Open/close code for raw IO.
+ *
+ * Set the device's soft blocksize to the minimum possible.  This gives the
+ * finest possible alignment and has no adverse impact on performance.
  */
-
-int raw_open(struct inode *inode, struct file *filp)
+static int raw_open(struct inode *inode, struct file *filp)
 {
-	int minor;
-	struct block_device * bdev;
+	const int minor = minor(inode->i_rdev);
+	struct block_device *bdev;
 	int err;
-	int sector_size;
-	int sector_bits;
 
-	minor = minor(inode->i_rdev);
-	
-	/* 
-	 * Is it the control device? 
-	 */
-	
-	if (minor == 0) {
+	if (minor == 0) {	/* It is the control device */
 		filp->f_op = &raw_ctl_fops;
 		return 0;
 	}
 	
-	down(&raw_devices[minor].mutex);
+	down(&raw_mutex);
+
 	/*
-	 * No, it is a normal raw device.  All we need to do on open is
-	 * to check that the device is bound, and force the underlying
-	 * block device to a sector-size blocksize. 
+	 * All we need to do on open is check that the device is bound.
 	 */
-
 	bdev = raw_devices[minor].binding;
 	err = -ENODEV;
-	if (!bdev)
-		goto out;
-
-	atomic_inc(&bdev->bd_count);
-	err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
-	if (err)
-		goto out;
-	
-	/*
-	 * Don't change the blocksize if we already have users using
-	 * this device 
-	 */
-
-	if (raw_devices[minor].inuse++)
-		goto out;
-
-	sector_size = bdev_hardsect_size(bdev);
-	raw_devices[minor].sector_size = sector_size;
-	for (sector_bits = 0; !(sector_size & 1); )
-		sector_size>>=1, sector_bits++;
-	raw_devices[minor].sector_bits = sector_bits;
-
- out:
-	up(&raw_devices[minor].mutex);
-	
+	if (bdev) {
+		atomic_inc(&bdev->bd_count);
+		err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW);
+		if (!err) {
+			err = set_blocksize(bdev, bdev_hardsect_size(bdev));
+			raw_devices[minor].inuse++;
+		}
+	}
+	up(&raw_mutex);
 	return err;
 }
 
-int raw_release(struct inode *inode, struct file *filp)
+static int raw_release(struct inode *inode, struct file *filp)
 {
-	int minor;
+	const int minor= minor(inode->i_rdev);
 	struct block_device *bdev;
 	
-	minor = minor(inode->i_rdev);
-	down(&raw_devices[minor].mutex);
+	down(&raw_mutex);
 	bdev = raw_devices[minor].binding;
 	raw_devices[minor].inuse--;
-	up(&raw_devices[minor].mutex);
+	up(&raw_mutex);
 	blkdev_put(bdev, BDEV_RAW);
 	return 0;
 }
 
-
-
-/* Forward ioctls to the underlying block device. */ 
-int raw_ioctl(struct inode *inode, 
-		  struct file *flip,
-		  unsigned int command, 
-		  unsigned long arg)
+/*
+ * Forward ioctls to the underlying block device.
+ */
+static int
+raw_ioctl(struct inode *inode, struct file *filp,
+		  unsigned int command, unsigned long arg)
 {
-	int minor = minor(inode->i_rdev), err; 
-	struct block_device *b; 
+	const int minor = minor(inode->i_rdev);
+	int err;
+	struct block_device *bdev;
+
+	err = -ENODEV;
 	if (minor < 1 && minor > 255)
-		return -ENODEV;
+		goto out;
 
-	b = raw_devices[minor].binding;
-	err = -EINVAL; 
-	if (b && b->bd_inode && b->bd_op && b->bd_op->ioctl) { 
-		err = b->bd_op->ioctl(b->bd_inode, NULL, command, arg); 
-	} 
+	bdev = raw_devices[minor].binding;
+	err = -EINVAL;
+	if (bdev == NULL)
+		goto out;
+	if (bdev->bd_inode && bdev->bd_op && bdev->bd_op->ioctl)
+		err = bdev->bd_op->ioctl(bdev->bd_inode, NULL, command, arg);
+out:
 	return err;
-} 
+}
 
 /*
  * Deal with ioctls against the raw-device control interface, to bind
- * and unbind other raw devices.  
+ * and unbind other raw devices.
  */
-
-int raw_ctl_ioctl(struct inode *inode, 
-		  struct file *flip,
-		  unsigned int command, 
-		  unsigned long arg)
+static int
+raw_ctl_ioctl(struct inode *inode, struct file *filp,
+		unsigned int command, unsigned long arg)
 {
 	struct raw_config_request rq;
-	int err = 0;
-	int minor;
+	struct raw_device_data *rawdev;
+	int err;
 	
 	switch (command) {
 	case RAW_SETBIND:
@@ -178,58 +119,64 @@
 
 		/* First, find out which raw minor we want */
 
-		if (copy_from_user(&rq, (void *) arg, sizeof(rq))) {
-			err = -EFAULT;
-			break;
-		}
+		err = -EFAULT;
+		if (copy_from_user(&rq, (void *) arg, sizeof(rq)))
+			goto out;
 		
-		minor = rq.raw_minor;
-		if (minor <= 0 || minor > MINORMASK) {
-			err = -EINVAL;
-			break;
-		}
+		err = -EINVAL;
+		if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK)
+			goto out;
+		rawdev = &raw_devices[rq.raw_minor];
 
 		if (command == RAW_SETBIND) {
 			/*
 			 * This is like making block devices, so demand the
 			 * same capability
 			 */
-			if (!capable(CAP_SYS_ADMIN)) {
-				err = -EPERM;
-				break;
-			}
+			err = -EPERM;
+			if (!capable(CAP_SYS_ADMIN))
+				goto out;
 
-			/* 
+			/*
 			 * For now, we don't need to check that the underlying
 			 * block device is present or not: we can do that when
 			 * the raw device is opened.  Just check that the
-			 * major/minor numbers make sense. 
+			 * major/minor numbers make sense.
 			 */
 
-			if ((rq.block_major == 0 && 
-			     rq.block_minor != 0) ||
-			    rq.block_major > MAX_BLKDEV ||
-			    rq.block_minor > MINORMASK) {
-				err = -EINVAL;
-				break;
-			}
+			err = -EINVAL;
+			if ((rq.block_major == 0 && rq.block_minor != 0) ||
+					rq.block_major > MAX_BLKDEV ||
+					rq.block_minor > MINORMASK)
+				goto out;
 			
-			down(&raw_devices[minor].mutex);
-			if (raw_devices[minor].inuse) {
-				up(&raw_devices[minor].mutex);
-				err = -EBUSY;
-				break;
+			down(&raw_mutex);
+			err = -EBUSY;
+			if (rawdev->inuse) {
+				up(&raw_mutex);
+				goto out;
+			}
+			if (rawdev->binding) {
+				bdput(rawdev->binding);
+				MOD_DEC_USE_COUNT;
 			}
-			if (raw_devices[minor].binding)
-				bdput(raw_devices[minor].binding);
-			raw_devices[minor].binding = 
-				bdget(kdev_t_to_nr(mk_kdev(rq.block_major, rq.block_minor)));
-			up(&raw_devices[minor].mutex);
+			if (rq.block_major == 0 && rq.block_minor == 0) {
+				/* unbind */
+				rawdev->binding = NULL;
+			} else {
+				kdev_t kdev;
+
+				kdev = mk_kdev(rq.block_major, rq.block_minor);
+				rawdev->binding = bdget(kdev_t_to_nr(kdev));
+				MOD_INC_USE_COUNT;
+			}
+			up(&raw_mutex);
 		} else {
 			struct block_device *bdev;
 			kdev_t dev;
 
-			bdev = raw_devices[minor].binding;
+			down(&raw_mutex);
+			bdev = rawdev->binding;
 			if (bdev) {
 				dev = to_kdev_t(bdev->bd_dev);
 				rq.block_major = major(dev);
@@ -237,59 +184,85 @@
 			} else {
 				rq.block_major = rq.block_minor = 0;
 			}
-			err = copy_to_user((void *) arg, &rq, sizeof(rq));
-			if (err)
-				err = -EFAULT;
+			up(&raw_mutex);
+			err = -EFAULT;
+			if (copy_to_user((void *)arg, &rq, sizeof(rq)))
+				goto out;
 		}
+		err = 0;
 		break;
 		
 	default:
 		err = -EINVAL;
+		break;
 	}
-	
+out:
 	return err;
 }
 
-ssize_t raw_read(struct file *filp, char * buf, size_t size, loff_t *offp)
-{
-	return rw_raw_dev(READ, filp, buf, size, offp);
-}
-
-ssize_t	raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp)
-{
-	return rw_raw_dev(WRITE, filp, (char *) buf, size, offp);
-}
-
-ssize_t
+static ssize_t
 rw_raw_dev(int rw, struct file *filp, char *buf, size_t size, loff_t *offp)
 {
-	struct block_device *bdev;
-	struct inode *inode;
-	int minor;
+	const int minor = minor(filp->f_dentry->d_inode->i_rdev);
+	struct block_device *bdev = raw_devices[minor].binding;
+	struct inode *inode = bdev->bd_inode;
 	ssize_t ret = 0;
 
-	minor = minor(filp->f_dentry->d_inode->i_rdev);
-	bdev = raw_devices[minor].binding;
-	inode = bdev->bd_inode;
-
 	if (size == 0)
 		goto out;
-	if (size < 0) {
-		ret = -EINVAL;
+	ret = -EINVAL;
+	if (size < 0)
 		goto out;
-	}
-	if (*offp >= inode->i_size) {
-		ret = -ENXIO;
+	ret = -ENXIO;
+	if (*offp >= inode->i_size)
 		goto out;
-	}
+
 	if (size + *offp > inode->i_size)
 		size = inode->i_size - *offp;
-
 	ret = generic_file_direct_IO(rw, inode, buf, *offp, size);
 	if (ret > 0)
 		*offp += ret;
-	if (inode->i_mapping->nrpages)
-		invalidate_inode_pages2(inode->i_mapping);
 out:
 	return ret;
 }
+
+static ssize_t
+raw_read(struct file *filp, char * buf, size_t size, loff_t *offp)
+{
+	return rw_raw_dev(READ, filp, buf, size, offp);
+}
+
+static ssize_t
+raw_write(struct file *filp, const char *buf, size_t size, loff_t *offp)
+{
+	return rw_raw_dev(WRITE, filp, (char *)buf, size, offp);
+}
+
+static struct file_operations raw_fops = {
+	.read	=	raw_read,
+	.write	=	raw_write,
+	.open	=	raw_open,
+	.release=	raw_release,
+	.ioctl	=	raw_ioctl,
+	.owner	=	THIS_MODULE,
+};
+
+static struct file_operations raw_ctl_fops = {
+	.ioctl	=	raw_ctl_ioctl,
+	.open	=	raw_open,
+	.owner	=	THIS_MODULE,
+};
+
+static int __init raw_init(void)
+{
+	register_chrdev(RAW_MAJOR, "raw", &raw_fops);
+	return 0;
+}
+
+static void __exit raw_exit(void)
+{
+	unregister_chrdev(RAW_MAJOR, "raw");
+}
+
+module_init(raw_init);
+module_exit(raw_exit);
diff -Nru a/drivers/char/rocket.c b/drivers/char/rocket.c
--- a/drivers/char/rocket.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/char/rocket.c	Thu Aug  1 14:17:36 2002
@@ -1881,15 +1881,23 @@
 {
 	int	num_aiops, num_chan;
 	int	aiop, chan;
+	int     extent = 0;
 	unsigned int	aiopio[MAX_AIOPS_PER_BOARD];	
 	CONTROLLER_t	*ctlp;
 
 	if (rcktpt_io_addr[i] == 0)
 		return(0);
 
-	if (check_region(rcktpt_io_addr[i],64)) {
+	if (rcktpt_io_addr[i] + 0x40 == controller) {
+		*reserved_controller = 1;
+		extent = 68;
+	} else {
+		extent = 64;
+	}
+	if (!request_region(rcktpt_io_addr[i], extent,
+			    "Comtrol Rocketport")) {
 		printk("RocketPort board address 0x%lx in use...\n",
-			rcktpt_io_addr[i]);
+		       rcktpt_io_addr[i]);
 		rcktpt_io_addr[i] = 0;
 		return(0);
 	}
@@ -1901,6 +1909,7 @@
 				    aiopio, MAX_AIOPS_PER_BOARD, 0,
 				    FREQ_DIS, 0);
 	if (num_aiops <= 0) {
+		release_region(rcktpt_io_addr[i], extent);
 		rcktpt_io_addr[i] = 0;
 		return(0);
 	}
@@ -1914,14 +1923,6 @@
 	printk("Rocketport controller #%d found at 0x%lx, "
 	       "%d AIOPs\n", i, rcktpt_io_addr[i],
 	       num_aiops);
-	if (rcktpt_io_addr[i] + 0x40 == controller) {
-		*reserved_controller = 1;
-		request_region(rcktpt_io_addr[i], 68,
-				       "Comtrol Rocketport");
-	} else {
-		request_region(rcktpt_io_addr[i], 64,
-			       "Comtrol Rocketport");
-	}
 	return(1);
 }
 
diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c
--- a/drivers/char/stallion.c	Thu Aug  1 14:17:37 2002
+++ b/drivers/char/stallion.c	Thu Aug  1 14:17:37 2002
@@ -810,7 +810,7 @@
 		return;
 	}
 	devfs_unregister (devfs_handle);
-	if ((i = devfs_unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
+	if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
 		printk("STALLION: failed to un-register serial memory device, "
 			"errno=%d\n", -i);
 
@@ -3208,7 +3208,7 @@
  *	Set up a character driver for per board stuff. This is mainly used
  *	to do stats ioctls on the ports.
  */
-	if (devfs_register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
+	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
 		printk("STALLION: failed to register serial board device\n");
 	devfs_handle = devfs_mk_dir (NULL, "staliomem", NULL);
 	devfs_register_series (devfs_handle, "%u", 4, DEVFS_FL_DEFAULT,
diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/tpqic02.c	Thu Aug  1 14:17:40 2002
@@ -2846,7 +2846,7 @@
 #endif
 	printk(TPQIC02_NAME ": DMA buffers: %u blocks\n", NR_BLK_BUF);
 	/* If we got this far, install driver functions */
-	if (devfs_register_chrdev
+	if (register_chrdev
 	    (QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops)) {
 		printk(TPQIC02_NAME ": Unable to get chrdev major %d\n",
 		       QIC02_TAPE_MAJOR);
@@ -2930,31 +2930,23 @@
 	if (status_zombie == NO) {
 		qic02_release_resources();
 	}
-	devfs_unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME);
-	devfs_unregister(devfs_find_handle
-			 (NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "tpqic11", QIC02_TAPE_MAJOR, 3,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "tpqic24", QIC02_TAPE_MAJOR, 5,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "tpqic120", QIC02_TAPE_MAJOR, 7,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8,
-			  DEVFS_SPECIAL_CHR, 0));
-	devfs_unregister(devfs_find_handle
-			 (NULL, "tpqic150", QIC02_TAPE_MAJOR, 9,
-			  DEVFS_SPECIAL_CHR, 0));
+	unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME);
+	devfs_find_and_unregister(NULL, "ntpqic11", QIC02_TAPE_MAJOR, 2,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "tpqic11", QIC02_TAPE_MAJOR, 3,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "ntpqic24", QIC02_TAPE_MAJOR, 4,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "tpqic24", QIC02_TAPE_MAJOR, 5,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "ntpqic120", QIC02_TAPE_MAJOR, 6,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "tpqic120", QIC02_TAPE_MAJOR, 7,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "ntpqic150", QIC02_TAPE_MAJOR, 8,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(NULL, "tpqic150", QIC02_TAPE_MAJOR, 9,
+				  DEVFS_SPECIAL_CHR, 0);
 }
 
 int init_module(void)
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/char/tty_io.c	Thu Aug  1 14:17:40 2002
@@ -2047,14 +2047,12 @@
 void tty_unregister_devfs (struct tty_driver *driver, unsigned minor)
 {
 #ifdef CONFIG_DEVFS_FS
-	void * handle;
 	int idx = minor - driver->minor_start;
 	char buf[32];
 
 	sprintf(buf, driver->name, idx + driver->name_base);
-	handle = devfs_find_handle (NULL, buf, driver->major, minor,
-				    DEVFS_SPECIAL_CHR, 0);
-	devfs_unregister (handle);
+	devfs_find_and_unregister(NULL, buf, driver->major, minor,
+				  DEVFS_SPECIAL_CHR, 0);
 #endif /* CONFIG_DEVFS_FS */
 }
 
@@ -2072,7 +2070,7 @@
 	if (driver->flags & TTY_DRIVER_INSTALLED)
 		return 0;
 
-	error = devfs_register_chrdev(driver->major, driver->name, &tty_fops);
+	error = register_chrdev(driver->major, driver->name, &tty_fops);
 	if (error < 0)
 		return error;
 	else if(driver->major == 0)
@@ -2119,11 +2117,11 @@
 		return -ENOENT;
 
 	if (othername == NULL) {
-		retval = devfs_unregister_chrdev(driver->major, driver->name);
+		retval = unregister_chrdev(driver->major, driver->name);
 		if (retval)
 			return retval;
 	} else
-		devfs_register_chrdev(driver->major, othername, &tty_fops);
+		register_chrdev(driver->major, othername, &tty_fops);
 
 	if (driver->prev)
 		driver->prev->next = driver->next;
diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
--- a/drivers/char/vc_screen.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/char/vc_screen.c	Thu Aug  1 14:17:39 2002
@@ -480,10 +480,10 @@
     sprintf (name, "a%u", index + 1);
     if (unregister)
     {
-	devfs_unregister ( devfs_find_handle (devfs_handle, name + 1, 0, 0,
-					      DEVFS_SPECIAL_CHR, 0) );
-	devfs_unregister ( devfs_find_handle (devfs_handle, name, 0, 0,
-					      DEVFS_SPECIAL_CHR, 0) );
+	devfs_find_and_unregister(devfs_handle, name + 1, 0, 0,
+				  DEVFS_SPECIAL_CHR, 0);
+	devfs_find_and_unregister(devfs_handle, name, 0, 0,
+				  DEVFS_SPECIAL_CHR, 0);
     }
     else
     {
@@ -501,7 +501,7 @@
 {
 	int error;
 
-	error = devfs_register_chrdev(VCS_MAJOR, "vcs", &vcs_fops);
+	error = register_chrdev(VCS_MAJOR, "vcs", &vcs_fops);
 
 	if (error)
 		printk("unable to get major %d for vcs device", VCS_MAJOR);
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/i2c/i2c-dev.c	Thu Aug  1 14:17:41 2002
@@ -489,11 +489,7 @@
 	printk(KERN_INFO "i2c-dev.o: i2c /dev entries driver module version %s (%s)\n", I2C_VERSION, I2C_DATE);
 
 	i2cdev_initialized = 0;
-#ifdef CONFIG_DEVFS_FS
-	if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) {
-#else
 	if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
-#endif
 		printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n",
 		       I2C_MAJOR);
 		return -EIO;
@@ -528,10 +524,8 @@
 	if (i2cdev_initialized >= 1) {
 #ifdef CONFIG_DEVFS_FS
 		devfs_unregister(devfs_handle);
-		if ((res = devfs_unregister_chrdev(I2C_MAJOR, "i2c"))) {
-#else
-		if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
 #endif
+		if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
 			printk(KERN_ERR "i2c-dev.o: unable to release major %d for i2c bus\n",
 			       I2C_MAJOR);
 			return res;
diff -Nru a/drivers/ide/ali14xx.c b/drivers/ide/ali14xx.c
--- a/drivers/ide/ali14xx.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/ide/ali14xx.c	Thu Aug  1 14:17:40 2002
@@ -107,13 +107,14 @@
  * Set PIO mode for the specified drive.
  * This function computes timing parameters
  * and sets controller registers accordingly.
+ * It assumes IRQ's are disabled or at least that no other process will
+ * attempt to access the IDE registers concurrently.
  */
 static void ali14xx_tune_drive(struct ata_device *drive, u8 pio)
 {
 	int drive_num;
 	int time1, time2;
 	u8 param1, param2, param3, param4;
-	unsigned long flags;
 	struct ata_timing *t;
 
 	if (pio == 255)
@@ -140,15 +141,12 @@
 
 	/* stuff timing parameters into controller registers */
 	drive_num = (drive->channel->index << 1) + drive->select.b.unit;
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
 	outb_p(reg_on, base_port);
 	out_reg(param1, reg_tab[drive_num].reg1);
 	out_reg(param2, reg_tab[drive_num].reg2);
 	out_reg(param3, reg_tab[drive_num].reg3);
 	out_reg(param4, reg_tab[drive_num].reg4);
 	outb_p(reg_off, base_port);
-	restore_flags(flags);	/* all CPUs */
 }
 
 /*
diff -Nru a/drivers/ide/ataraid.c b/drivers/ide/ataraid.c
--- a/drivers/ide/ataraid.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/ide/ataraid.c	Thu Aug  1 14:17:40 2002
@@ -45,7 +45,6 @@
 
 
 struct gendisk ataraid_gendisk;
-static int ataraid_gendisk_sizes[256];
 static int ataraid_readahead[256];
 
 static struct block_device_operations ataraid_fops = {
@@ -257,7 +256,6 @@
 	ataraid_gendisk.major = ATAMAJOR;
 	ataraid_gendisk.major_name = "ataraid";
 	ataraid_gendisk.minor_shift = 4;
-	ataraid_gendisk.sizes = &ataraid_gendisk_sizes[0];
 	ataraid_gendisk.nr_real = 16;
 	ataraid_gendisk.fops = &ataraid_fops;
 
@@ -282,7 +280,6 @@
 static void __exit ataraid_exit(void)
 {
 	unregister_blkdev(ATAMAJOR, "ataraid");
-	blk_size[ATAMAJOR] = NULL;
 
 	del_gendisk(&ataraid_gendisk);
 
diff -Nru a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
--- a/drivers/ide/cmd640.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/ide/cmd640.c	Thu Aug  1 14:17:40 2002
@@ -109,6 +109,7 @@
 #include <linux/init.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/pci.h>
 
 #include <asm/io.h>
 
@@ -164,6 +165,12 @@
 #define BRST		0x59
 
 /*
+ * Protects register file access from overlapping on primary and secondary
+ * channel, since those share hardware resources.
+ */
+static spinlock_t cmd640_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
+
+/*
  * Registers and masks for easy access by drive index:
  */
 static u8 prefetch_regs[4]  = {CNTRL, CNTRL, ARTTIM23, ARTTIM23};
@@ -171,12 +178,6 @@
 
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
 
-/*
- * Protects register file access from overlapping on primary and secondary
- * channel, since those share hardware resources.
- */
-static spinlock_t cmd640_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED;
-
 static u8 arttim_regs[4] = {ARTTIM0, ARTTIM1, ARTTIM23, ARTTIM23};
 static u8 drwtim_regs[4] = {DRWTIM0, DRWTIM1, DRWTIM23, DRWTIM23};
 
@@ -214,19 +215,16 @@
  * Therefore, we must use direct IO instead.
  */
 
-/* This is broken, but no more so than the old code.. */
-static spinlock_t cmd640_lock = SPIN_LOCK_UNLOCKED;
-
 /* PCI method 1 access */
 
 static void put_cmd640_reg_pci1 (unsigned short reg, u8 val)
 {
 	unsigned long flags;
-
-	spin_lock_irqsave(&cmd640_lock, flags);
-	outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
+	
+	spin_lock_irqsave(&pci_lock, flags);
+	outb_p((reg & 0xfc) | cmd640_key, 0xcf8);
 	outb_p(val, (reg & 3) | 0xcfc);
-	spin_unlock_irqrestore(&cmd640_lock, flags);
+	spin_unlock_irqrestore(&pci_lock, flags);
 }
 
 static u8 get_cmd640_reg_pci1 (unsigned short reg)
@@ -234,10 +232,10 @@
 	u8 b;
 	unsigned long flags;
 
-	spin_lock_irqsave(&cmd640_lock, flags);
-	outl_p((reg & 0xfc) | cmd640_key, 0xcf8);
-	b = inb_p((reg & 3) | 0xcfc);
-	spin_unlock_irqrestore(&cmd640_lock, flags);
+	spin_lock_irqsave(&pci_lock, flags);
+	outb_p((reg & 0xfc) | cmd640_key, 0xcf8);
+	b=inb_p((reg & 3) | 0xcfc);
+	spin_unlock_irqrestore(&pci_lock, flags);
 	return b;
 }
 
@@ -247,11 +245,11 @@
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&cmd640_lock, flags);
+	spin_lock_irqsave(&pci_lock, flags);
 	outb_p(0x10, 0xcf8);
 	outb_p(val, cmd640_key + reg);
 	outb_p(0, 0xcf8);
-	spin_unlock_irqrestore(&cmd640_lock, flags);
+	spin_unlock_irqrestore(&pci_lock, flags);
 }
 
 static u8 get_cmd640_reg_pci2 (unsigned short reg)
@@ -259,11 +257,11 @@
 	u8 b;
 	unsigned long flags;
 
-	spin_lock_irqsave(&cmd640_lock, flags);
+	spin_lock_irqsave(&pci_lock, flags);
 	outb_p(0x10, 0xcf8);
 	b = inb_p(cmd640_key + reg);
 	outb_p(0, 0xcf8);
-	spin_unlock_irqrestore(&cmd640_lock, flags);
+	spin_unlock_irqrestore(&pci_lock, flags);
 	return b;
 }
 
@@ -574,7 +572,7 @@
 	/*
 	 * Now that everything is ready, program the new timings
 	 */
-	spin_lock(&cmd640_lock, flags);
+	spin_lock_irqsave(&cmd640_lock, flags);
 	/*
 	 * Program the address_setup clocks into ARTTIM reg,
 	 * and then the active/recovery counts into the DRWTIM reg
@@ -695,9 +693,61 @@
 
 #endif
 
+/**
+ *	pci_conf1	-	check for PCI type 1 configuration
+ *	
+ *	Issues a safe probe sequence for PCI configuration type 1 and
+ *	returns non-zero if conf1 is supported. Takes the pci_config lock
+ */
+ 
+static int pci_conf1(void)
+{
+	u32 tmp;
+	unsigned long flags;
+	
+	spin_lock_irqsave(&pci_lock, flags);
+
+	OUT_BYTE(0x01, 0xCFB);
+	tmp = inl(0xCF8);
+	outl(0x80000000, 0xCF8);
+	if (inl(0xCF8) == 0x80000000) {
+		spin_unlock_irqrestore(&pci_lock, flags);
+		outl(tmp, 0xCF8);
+		return 1;
+	}
+	outl(tmp, 0xCF8);
+	spin_unlock_irqrestore(&pci_lock, flags);
+	return 0;
+}
+
+/**
+ *	pci_conf2	-	check for PCI type 2 configuration
+ *	
+ *	Issues a safe probe sequence for PCI configuration type 2 and
+ *	returns non-zero if conf2 is supported. Takes the pci_config lock.
+ */
+ 
+
+static int pci_conf2(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&pci_lock, flags);
+	
+	OUT_BYTE(0x00, 0xCFB);
+	OUT_BYTE(0x00, 0xCF8);
+	OUT_BYTE(0x00, 0xCFA);
+	if (IN_BYTE(0xCF8) == 0x00 && IN_BYTE(0xCFA) == 0x00) {
+		spin_unlock_irqrestore(&pci_lock, flags);
+		return 1;
+	}
+	spin_unlock_irqrestore(&pci_lock, flags);
+	return 0;
+}
+
 /*
  * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
  */
+
 int __init ide_probe_for_cmd640x(void)
 {
 #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
@@ -712,9 +762,9 @@
 		bus_type = "VLB";
 	} else {
 		cmd640_vlb = 0;
-		if (probe_for_cmd640_pci1())
+		if (pci_conf1() && probe_for_cmd640_pci1())
 			bus_type = "PCI (type1)";
-		else if (probe_for_cmd640_pci2())
+		else if (pci_conf2() && probe_for_cmd640_pci2())
 			bus_type = "PCI (type2)";
 		else
 			return 0;
diff -Nru a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c
--- a/drivers/ide/cs5530.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/ide/cs5530.c	Thu Aug  1 14:17:41 2002
@@ -58,19 +58,18 @@
  * After chip reset, the PIO timings are set to 0x0000e132, which is not valid.
  */
 #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
-#define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->unit ? 0x30 : 0x20))
+#define CS5530_BASEREG(ch)	(((ch)->dma_base & ~0xf) + ((ch)->unit ? 0x30 : 0x20))
 
 /*
- * cs5530_tuneproc() handles selection/setting of PIO modes
- * for both the chipset and drive.
+ * Handle selection/setting of PIO modes for both the chipset and drive.
  *
- * The ide_init_cs5530() routine guarantees that all drives
- * will have valid default PIO timings set up before we get here.
+ * The ide_init_cs5530() routine guarantees that all drives will have valid
+ * default PIO timings set up before we get here.
  */
 static void cs5530_tuneproc(struct ata_device *drive, u8 pio)
 {
-	struct ata_channel *hwif = drive->channel;
-	unsigned int	format, basereg = CS5530_BASEREG(hwif);
+	unsigned int format;
+	unsigned int basereg = CS5530_BASEREG(drive->channel);
 
 	if (pio == 255)
 		pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO);
@@ -84,25 +83,26 @@
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
+
 /*
- * cs5530_config_dma() handles selection/setting of DMA/UDMA modes
- * for both the chipset and drive.
+ * Handle selection/setting of DMA/UDMA modes for both the chipset and drive.
  */
 static int cs5530_config_dma(struct ata_device *drive)
 {
-	int			udma_ok = 1, mode = 0;
-	struct ata_channel *hwif = drive->channel;
-	int			unit = drive->select.b.unit;
-	struct ata_device		*mate = &hwif->drives[unit^1];
-	struct hd_driveid	*id = drive->id;
-	unsigned int		basereg, reg, timings;
+	int udma_ok = 1;
+	int mode = 0;
+	struct ata_channel *ch = drive->channel;
+	int unit = drive->select.b.unit;
+	struct ata_device *mate = &ch->drives[unit^1];
+	struct hd_driveid *id = drive->id;
+	unsigned int basereg, reg, timings;
 
 
 	/*
 	 * Default to DMA-off in case we run into trouble here.
 	 */
 	udma_enable(drive, 0, 0);
-	outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
+	outb(inb(ch->dma_base+2)&~(unit?0x40:0x20), ch->dma_base+2); /* clear DMA_capable bit */
 
 	/*
 	 * The CS5530 specifies that two drives sharing a cable cannot
@@ -129,7 +129,7 @@
 	 * Now see what the current drive is capable of,
 	 * selecting UDMA only if the mate said it was ok.
 	 */
-	if (id && (id->capability & 1) && hwif->autodma && !udma_black_list(drive)) {
+	if (id && (id->capability & 1) && ch->autodma && !udma_black_list(drive)) {
 		if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
 			if      (id->dma_ultra & 4)
 				mode = XFER_UDMA_2;
@@ -168,7 +168,7 @@
 			printk("%s: cs5530_config_dma: huh? mode=%02x\n", drive->name, mode);
 			return 1;	/* failure */
 	}
-	basereg = CS5530_BASEREG(hwif);
+	basereg = CS5530_BASEREG(ch);
 	reg = inl(basereg+4);			/* get drive0 config register */
 	timings |= reg & 0x80000000;		/* preserve PIO format bit */
 	if (unit == 0) {			/* are we configuring drive0? */
@@ -181,7 +181,7 @@
 		outl(reg,     basereg+4);	/* write drive0 config register */
 		outl(timings, basereg+12);	/* write drive1 config register */
 	}
-	outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2);	/* set DMA_capable bit */
+	outb(inb(ch->dma_base+2)|(unit?0x40:0x20), ch->dma_base+2);	/* set DMA_capable bit */
 
 	/*
 	 * Finally, turn DMA on in software, and exit.
@@ -202,7 +202,8 @@
  */
 static unsigned int __init pci_init_cs5530(struct pci_dev *dev)
 {
-	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL;
+	struct pci_dev *master_0 = NULL;
+	struct pci_dev *cs5530_0 = NULL;
 	unsigned short pcicmd = 0;
 	unsigned long flags;
 
@@ -218,6 +219,7 @@
 			}
 		}
 	}
+
 	if (!master_0) {
 		printk("%s: unable to locate PCI MASTER function\n", dev->name);
 		return 0;
@@ -227,15 +229,13 @@
 		return 0;
 	}
 
-	save_flags(flags);
-	cli();	/* all CPUs (there should only be one CPU with this chipset) */
-
 	/*
 	 * Enable BusMaster and MemoryWriteAndInvalidate for the cs5530:
 	 * -->  OR 0x14 into 16-bit PCI COMMAND reg of function 0 of the cs5530
 	 */
-	pci_read_config_word (cs5530_0, PCI_COMMAND, &pcicmd);
-	pci_write_config_word(cs5530_0, PCI_COMMAND, pcicmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
+	 
+	pci_set_master(cs5530_0);
+	pci_set_mwi(cs5530_0);
 
 	/*
 	 * Set PCI CacheLineSize to 16-bytes:
@@ -274,41 +274,44 @@
 	pci_write_config_byte(master_0, 0x42, 0x00);
 	pci_write_config_byte(master_0, 0x43, 0xc1);
 
-	restore_flags(flags);
-
 	return 0;
 }
 
 /*
- * This gets invoked by the IDE driver once for each channel,
- * and performs channel-specific pre-initialization before drive probing.
+ * This gets invoked once for each channel, and performs channel-specific
+ * pre-initialization before drive probing.
  */
-static void __init ide_init_cs5530(struct ata_channel *hwif)
+static void __init ide_init_cs5530(struct ata_channel *ch)
 {
-	u32 basereg, d0_timings;
+	u32 basereg;
+	u32 d0_timings;
 
-	hwif->serialized = 1;
+	ch->serialized = 1;
+
+	/* We think a 64kB transfer is a 0 byte transfer, so set our
+	   segment size to be one sector smaller than 64kB. */
+	ch->max_segment_size = (1<<16) - 512;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-	if (hwif->dma_base) {
-		hwif->highmem = 1;
-		hwif->udma_setup = cs5530_udma_setup;
+	if (ch->dma_base) {
+		ch->highmem = 1;
+		ch->udma_setup = cs5530_udma_setup;
 	}
 #endif
 
-		hwif->tuneproc = &cs5530_tuneproc;
-		basereg = CS5530_BASEREG(hwif);
-		d0_timings = inl(basereg+0);
-		if (CS5530_BAD_PIO(d0_timings)) {	/* PIO timings not initialized? */
-			outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
-			if (!hwif->drives[0].autotune)
-				hwif->drives[0].autotune = 1;	/* needs autotuning later */
-		}
-		if (CS5530_BAD_PIO(inl(basereg+8))) {	/* PIO timings not initialized? */
-			outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
-			if (!hwif->drives[1].autotune)
-				hwif->drives[1].autotune = 1;	/* needs autotuning later */
-		}
+	ch->tuneproc = &cs5530_tuneproc;
+	basereg = CS5530_BASEREG(ch);
+	d0_timings = inl(basereg+0);
+	if (CS5530_BAD_PIO(d0_timings)) {	/* PIO timings not initialized? */
+		outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+0);
+		if (!ch->drives[0].autotune)
+			ch->drives[0].autotune = 1;	/* needs autotuning later */
+	}
+	if (CS5530_BAD_PIO(inl(basereg+8))) {	/* PIO timings not initialized? */
+		outl(cs5530_pio_timings[(d0_timings>>31)&1][0], basereg+8);
+		if (!ch->drives[1].autotune)
+			ch->drives[1].autotune = 1;	/* needs autotuning later */
+	}
 }
 
 
diff -Nru a/drivers/ide/dtc2278.c b/drivers/ide/dtc2278.c
--- a/drivers/ide/dtc2278.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/ide/dtc2278.c	Thu Aug  1 14:17:40 2002
@@ -66,21 +66,18 @@
 	}
 }
 
+/* Assumes IRQ's are disabled or at least that no other process will
+   attempt to access the IDE registers concurrently. */
 static void tune_dtc2278(struct ata_device *drive, u8 pio)
 {
-	unsigned long flags;
-
 	pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
 
 	if (pio >= 3) {
-		save_flags(flags);	/* all CPUs */
-		cli();			/* all CPUs */
 		/*
 		 * This enables PIO mode4 (3?) on the first interface
 		 */
 		sub22(1,0xc3);
 		sub22(0,0xa0);
-		restore_flags(flags);	/* all CPUs */
 	} else {
 		/* we don't know how to set it back again.. */
 	}
diff -Nru a/drivers/ide/hd.c b/drivers/ide/hd.c
--- a/drivers/ide/hd.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/hd.c	Thu Aug  1 14:17:36 2002
@@ -1,15 +1,11 @@
 /*
- *  linux/drivers/ide/hd.c
- *
  *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-/*
+ *
  * This is the low-level hd interrupt support. It traverses the
  * request-list, using interrupts to jump between functions. As
  * all the functions are called within interrupts, we may not
  * sleep. Special care is recommended.
- * 
+ *
  *  modified by Drew Eckhardt to check nr of hd's from the CMOS.
  *
  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
@@ -26,18 +22,16 @@
  *  Bugfix: max_sectors must be <= 255 or the wheels tend to come
  *  off in a hurry once you queue things up - Paul G. 02/2001
  */
-  
+
 /* Uncomment the following if you want verbose error reports. */
 /* #define VERBOSE_ERRORS */
-  
+
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/fs.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/kernel.h>
-#include <linux/hdreg.h>
 #include <linux/genhd.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -45,6 +39,7 @@
 #include <linux/mc146818rtc.h> /* CMOS defines */
 #include <linux/init.h>
 #include <linux/blkpg.h>
+#include <linux/hdreg.h>
 
 #define REALLY_SLOW_IO
 #include <asm/system.h>
@@ -55,6 +50,15 @@
 #define DEVICE_NR(device) (minor(device)>>6)
 #include <linux/blk.h>
 
+/* ATA commands we use.
+ */
+#define WIN_SPECIFY	0x91 /* set drive geometry translation */
+#define WIN_RESTORE	0x10
+#define WIN_READ	0x20 /* 28-Bit */
+#define WIN_WRITE	0x30 /* 28-Bit */
+
+#define HD_IRQ 14	/* the standard disk interrupt */
+
 #ifdef __arm__
 #undef  HD_IRQ
 #endif
@@ -63,6 +67,45 @@
 #define HD_IRQ IRQ_HARDDISK
 #endif
 
+/* Hd controller regster ports */
+
+#define HD_DATA		0x1f0		/* _CTL when writing */
+#define HD_ERROR	0x1f1		/* see err-bits */
+#define HD_NSECTOR	0x1f2		/* nr of sectors to read/write */
+#define HD_SECTOR	0x1f3		/* starting sector */
+#define HD_LCYL		0x1f4		/* starting cylinder */
+#define HD_HCYL		0x1f5		/* high byte of starting cyl */
+#define HD_CURRENT	0x1f6		/* 101dhhhh , d=drive, hhhh=head */
+#define HD_STATUS	0x1f7		/* see status-bits */
+#define HD_FEATURE	HD_ERROR	/* same io address, read=error, write=feature */
+#define HD_PRECOMP	HD_FEATURE	/* obsolete use of this port - predates IDE */
+#define HD_COMMAND	HD_STATUS	/* same io address, read=status, write=cmd */
+
+#define HD_CMD		0x3f6		/* used for resets */
+#define HD_ALTSTATUS	0x3f6		/* same as HD_STATUS but doesn't clear irq */
+
+/* Bits of HD_STATUS */
+#define ERR_STAT		0x01
+#define INDEX_STAT		0x02
+#define ECC_STAT		0x04	/* Corrected error */
+#define DRQ_STAT		0x08
+#define SEEK_STAT		0x10
+#define SERVICE_STAT		SEEK_STAT
+#define WRERR_STAT		0x20
+#define READY_STAT		0x40
+#define BUSY_STAT		0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR		0x01	/* Bad address mark */
+#define TRK0_ERR		0x02	/* couldn't find track 0 */
+#define ABRT_ERR		0x04	/* Command aborted */
+#define MCR_ERR			0x08	/* media change request */
+#define ID_ERR			0x10	/* ID field not found */
+#define MC_ERR			0x20	/* media changed */
+#define ECC_ERR			0x40	/* Uncorrectable ECC error */
+#define BBD_ERR			0x80	/* pre-EIDE meaning:  block marked bad */
+#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
+
 static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
 
 static int revalidate_hddisk(kdev_t, int);
@@ -105,7 +148,6 @@
 #endif
 
 static struct hd_struct hd[MAX_HD<<6];
-static int hd_sizes[MAX_HD<<6];
 
 static struct timer_list device_timer;
 
@@ -162,12 +204,9 @@
 
 static void dump_status (const char *msg, unsigned int stat)
 {
-	unsigned long flags;
 	char devc;
 
 	devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
-	save_flags (flags);
-	sti();
 #ifdef VERBOSE_ERRORS
 	printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
 	if (stat & BUSY_STAT)	printk("Busy ");
@@ -207,8 +246,7 @@
 		hd_error = inb(HD_ERROR);
 		printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
 	}
-#endif	/* verbose errors */
-	restore_flags (flags);
+#endif
 }
 
 void check_status(void)
@@ -467,7 +505,7 @@
 	if (i > 0) {
 		SET_HANDLER(&write_intr);
 		outsw(HD_DATA,CURRENT->buffer,256);
-		sti();
+		local_irq_enable();
 	} else {
 #if (HD_DELAY > 0)
 		last_req = read_timer();
@@ -500,7 +538,7 @@
 		return;
 
 	disable_irq(HD_IRQ);
-	sti();
+	local_irq_enable();
 	reset = 1;
 	dev = DEVICE_NR(CURRENT->rq_dev);
 	printk("hd%c: timeout\n", dev+'a');
@@ -510,7 +548,7 @@
 #endif
 		end_request(CURRENT, 0);
 	}
-	cli();
+	local_irq_disable();
 	hd_request();
 	enable_irq(HD_IRQ);
 }
@@ -548,7 +586,7 @@
 		return;
 repeat:
 	del_timer(&device_timer);
-	sti();
+	local_irq_enable();
 
 	if (blk_queue_empty(QUEUE)) {
 		do_hd = NULL;
@@ -556,7 +594,7 @@
 	}
 
 	if (reset) {
-		cli();
+		local_irq_disable();
 		reset_hd();
 		return;
 	}
@@ -670,13 +708,22 @@
 
 extern struct block_device_operations hd_fops;
 
-static struct gendisk hd_gendisk = {
+static struct gendisk hd_gendisk[2] = {
+{
 	.major =	MAJOR_NR,
+	.first_minor =	0,
 	.major_name =	"hd",
 	.minor_shift =	6,
 	.part =		hd,
-	.sizes =	hd_sizes,
 	.fops =		&hd_fops,
+},{
+	.major =	MAJOR_NR,
+	.first_minor =	64,
+	.major_name =	"hd",
+	.minor_shift =	6,
+	.part =		hd + 64,
+	.fops =		&hd_fops,
+}
 };
 	
 static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
@@ -688,7 +735,7 @@
 	if (!handler)
 		handler = unexpected_hd_interrupt;
 	handler();
-	sti();
+	local_irq_enable();
 }
 
 static struct block_device_operations hd_fops = {
@@ -808,23 +855,24 @@
 		return;
 	}
 
-	hd_gendisk.nr_real = NR_HD;
-
-	for(drive=0; drive < NR_HD; drive++)
-		register_disk(&hd_gendisk, mk_kdev(MAJOR_NR,drive<<6), 1<<6,
+	for(drive=0; drive < NR_HD; drive++) {
+		hd_gendisk[i].nr_real = 1;
+		add_gendisk(hd_gendisk + drive);
+		register_disk(hd_gendisk + drive,
+			mk_kdev(MAJOR_NR,drive<<6), 1<<6,
 			&hd_fops, hd_info[drive].head * hd_info[drive].sect *
 			hd_info[drive].cyl);
+	}
 }
 
 int __init hd_init(void)
 {
-	if (devfs_register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
+	if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
 		printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
 		return -1;
 	}
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
 	blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
-	add_gendisk(&hd_gendisk);
 	init_timer(&device_timer);
 	device_timer.function = hd_times_out;
 	hd_geninit();
diff -Nru a/drivers/ide/ht6560b.c b/drivers/ide/ht6560b.c
--- a/drivers/ide/ht6560b.c	Thu Aug  1 14:17:37 2002
+++ b/drivers/ide/ht6560b.c	Thu Aug  1 14:17:37 2002
@@ -249,12 +249,8 @@
  */
 static void ht_set_prefetch(struct ata_device *drive, u8 state)
 {
-	unsigned long flags;
 	int t = HT_PREFETCH_MODE << 8;
 
-	save_flags (flags);	/* all CPUs */
-	cli();		        /* all CPUs */
-
 	/*
 	 *  Prefetch mode and unmask irq seems to conflict
 	 */
@@ -267,16 +263,16 @@
 		drive->channel->no_unmask = 0;
 	}
 
-	restore_flags (flags);	/* all CPUs */
-
 #ifdef DEBUG
 	printk("ht6560b: drive %s prefetch mode %sabled\n", drive->name, (state ? "en" : "dis"));
 #endif
 }
 
+/* Assumes IRQ's are disabled or at least that no other process will attempt to
+ * access the IDE registers concurrently.
+ */
 static void tune_ht6560b(struct ata_device *drive, u8 pio)
 {
-	unsigned long flags;
 	u8 timing;
 
 	switch (pio) {
@@ -288,13 +284,8 @@
 
 	timing = ht_pio2timings(drive, pio);
 
-	save_flags (flags);	/* all CPUs */
-	cli();		        /* all CPUs */
-
 	drive->drive_data &= 0xff00;
 	drive->drive_data |= timing;
-
-	restore_flags (flags);	/* all CPUs */
 
 #ifdef DEBUG
 	printk("ht6560b: drive %s tuned to pio mode %#x timing=%#x\n", drive->name, pio, timing);
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/ide/ide-cd.c	Thu Aug  1 14:17:40 2002
@@ -305,8 +305,9 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
-#include <linux/ide.h>
 #include <linux/completion.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
 
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -1616,16 +1617,11 @@
 
 	if (rq->flags & REQ_CMD) {
 		if (CDROM_CONFIG_FLAGS(drive)->seeking) {
-			unsigned long elpased = jiffies - info->start_seek;
-
-			if (!ata_status(drive, SEEK_STAT, 0)) {
-				if (elpased < IDECD_SEEK_TIMEOUT) {
-					ide_stall_queue(drive, IDECD_SEEK_TIMER);
-					return ATA_OP_FINISHED;
-				}
+			if (ATA_OP_READY != ata_status_poll(drive, SEEK_STAT, 0, IDECD_SEEK_TIMEOUT, rq)) {
 				printk ("%s: DSC timeout\n", drive->name);
-			}
-			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+				CDROM_CONFIG_FLAGS(drive)->seeking = 0;
+			} else
+				return ATA_OP_FINISHED;
 		}
 		if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
 			ret = cdrom_start_seek(drive, rq, block);
@@ -2016,7 +2012,6 @@
 	if (stat)
 		toc->capacity = 0x1fffff;
 
-	drive->channel->gd->sizes[drive->select.b.unit << PARTN_BITS] = (toc->capacity * SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
 
 	/* Remember that we've read this stuff. */
@@ -2882,7 +2877,6 @@
 {
 	struct cdrom_info *info = drive->driver_data;
 	struct atapi_toc *toc;
-	int minor = drive->select.b.unit << PARTN_BITS;
 	struct request_sense sense;
 
 	cdrom_read_toc(drive, &sense);
@@ -2894,8 +2888,6 @@
 
 	/* for general /dev/cdrom like mounting, one big disc */
 	drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
-	drive->channel->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
-	blk_size[drive->channel->major] = drive->channel->gd->sizes;
 }
 
 static sector_t ide_cdrom_capacity(struct ata_device *drive)
@@ -2914,7 +2906,7 @@
 	struct cdrom_info *info = drive->driver_data;
 	struct cdrom_device_info *devinfo = &info->devinfo;
 
-	if (ide_unregister_subdriver (drive))
+	if (ata_unregister_device(drive))
 		return 1;
 	if (info->buffer != NULL)
 		kfree(info->buffer);
@@ -2973,7 +2965,7 @@
 		printk(KERN_ERR "%s: Can't allocate a cdrom structure\n", drive->name);
 		return;
 	}
-	if (ide_register_subdriver (drive, &ide_cdrom_driver)) {
+	if (ata_register_device(drive, &ide_cdrom_driver)) {
 		printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name);
 		kfree (info);
 		return;
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/ide-disk.c	Thu Aug  1 14:17:36 2002
@@ -723,7 +723,7 @@
 
 static sector_t idedisk_capacity(struct ata_device *drive)
 {
-	return drive->capacity - drive->sect0;
+	return drive->capacity;
 }
 
 /*
@@ -1064,9 +1064,9 @@
 		if (drive != &ch->drives[i])
 		    continue;
 		drvid = i;
-		ch->gd->de_arr[i] = drive->de;
+		ch->gd[i]->de_arr[0] = drive->de;
 		if (drive->removable)
-			ch->gd->flags[i] |= GENHD_FL_REMOVABLE;
+			ch->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
 		break;
 	}
 
@@ -1279,7 +1279,7 @@
 			printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
 				drive->name);
 	}
-	ret = ide_unregister_subdriver(drive);
+	ret = ata_unregister_device(drive);
 
 	/* FIXME: This is killing the kernel with BUG 185 at asm/spinlocks.h
 	 * horribly.  Check whatever we did REGISTER the device properly
@@ -1471,8 +1471,8 @@
 	if (req[0] != '\0' && strcmp(req, "ide-disk"))
 		return;
 
-	if (ide_register_subdriver(drive, &idedisk_driver)) {
-		printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
+	if (ata_register_device(drive, &idedisk_driver)) {
+		printk(KERN_ERR "%s: Failed to register the driver with ide.c\n", drive->name);
 		return;
 	}
 
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/ide/ide-floppy.c	Thu Aug  1 14:17:39 2002
@@ -94,9 +94,10 @@
 #include <linux/genhd.h>
 #include <linux/slab.h>
 #include <linux/cdrom.h>
+#include <linux/buffer_head.h>
+#include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/atapi.h>
-#include <linux/buffer_head.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -1711,9 +1712,9 @@
 		struct ata_channel *hwif = drive->channel;
 
 		if (drive != &hwif->drives[i]) continue;
-		hwif->gd->de_arr[i] = drive->de;
+		hwif->gd[i]->de_arr[0] = drive->de;
 		if (drive->removable)
-			hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;
+			hwif->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
 		break;
 	}
 }
@@ -1722,10 +1723,10 @@
 {
 	idefloppy_floppy_t *floppy = drive->driver_data;
 
-	if (ide_unregister_subdriver (drive))
+	if (ata_unregister_device(drive))
 		return 1;
 	drive->driver_data = NULL;
-	kfree (floppy);
+	kfree(floppy);
 	return 0;
 }
 
@@ -1779,7 +1780,7 @@
 				drive->name);
 		return;
 	}
-	if (ide_register_subdriver(drive, &idefloppy_driver)) {
+	if (ata_register_device(drive, &idefloppy_driver)) {
 		printk(KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
 		kfree (floppy);
 		return;
diff -Nru a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
--- a/drivers/ide/ide-pci.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/ide/ide-pci.c	Thu Aug  1 14:17:41 2002
@@ -550,7 +550,8 @@
 	if (!dev2) {
 		return;
 	} else {
-		byte irq = 0, irq2 = 0;
+		u8 irq = 0;
+		u8 irq2 = 0;
 		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
 		pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2);
 		if (irq != irq2) {
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/ide-tape.c	Thu Aug  1 14:17:36 2002
@@ -7,400 +7,17 @@
  *
  * It is hereby placed under the terms of the GNU general public license.
  * (See linux/COPYING).
- */
-
-/*
- * BIG FAT FIXME: clean tape->spinlock locking  --bzolnier
- */
-
-/*
- * IDE ATAPI streaming tape driver.
  *
- * This driver is a part of the Linux ide driver and works in co-operation
- * with linux/drivers/block/ide.c.
+ * Contributors:
  *
- * The driver, in co-operation with ide.c, basically traverses the
- * request-list for the block device interface. The character device
- * interface, on the other hand, creates new requests, adds them
- * to the request-list of the block device, and waits for their completion.
- *
- * Pipelined operation mode is now supported on both reads and writes.
- *
- * The block device major and minor numbers are determined from the
- * tape's relative position in the ide interfaces, as explained in ide.c.
- *
- * The character device interface consists of the following devices:
- *
- * ht0		major 37, minor 0	first  IDE tape, rewind on close.
- * ht1		major 37, minor 1	second IDE tape, rewind on close.
- * ...
- * nht0		major 37, minor 128	first  IDE tape, no rewind on close.
- * nht1		major 37, minor 129	second IDE tape, no rewind on close.
- * ...
- *
- * Run linux/scripts/MAKEDEV.ide to create the above entries.
- *
- * The general magnetic tape commands compatible interface, as defined by
- * include/linux/mtio.h, is accessible through the character device.
- *
- * General ide driver configuration options, such as the interrupt-unmask
- * flag, can be configured by issuing an ioctl to the block device interface,
- * as any other ide device.
- *
- * Our own ide-tape ioctl's can be issued to either the block device or
- * the character device interface.
- *
- * Maximal throughput with minimal bus load will usually be achieved in the
- * following scenario:
- *
- *	1.	ide-tape is operating in the pipelined operation mode.
- *	2.	No buffering is performed by the user backup program.
- *
- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
- * 
- * Ver 0.1   Nov  1 95   Pre-working code :-)
- * Ver 0.2   Nov 23 95   A short backup (few megabytes) and restore procedure
- *                        was successful ! (Using tar cvf ... on the block
- *                        device interface).
- *                       A longer backup resulted in major swapping, bad
- *                        overall Linux performance and eventually failed as
- *                        we received non serial read-ahead requests from the
- *                        buffer cache.
- * Ver 0.3   Nov 28 95   Long backups are now possible, thanks to the
- *                        character device interface. Linux's responsiveness
- *                        and performance doesn't seem to be much affected
- *                        from the background backup procedure.
- *                       Some general mtio.h magnetic tape operations are
- *                        now supported by our character device. As a result,
- *                        popular tape utilities are starting to work with
- *                        ide tapes :-)
- *                       The following configurations were tested:
- *                       	1. An IDE ATAPI TAPE shares the same interface
- *                       	   and irq with an IDE ATAPI CDROM.
- *                        	2. An IDE ATAPI TAPE shares the same interface
- *                          	   and irq with a normal IDE disk.
- *                        Both configurations seemed to work just fine !
- *                        However, to be on the safe side, it is meanwhile
- *                        recommended to give the IDE TAPE its own interface
- *                        and irq.
- *                       The one thing which needs to be done here is to
- *                        add a "request postpone" feature to ide.c,
- *                        so that we won't have to wait for the tape to finish
- *                        performing a long media access (DSC) request (such
- *                        as a rewind) before we can access the other device
- *                        on the same interface. This effect doesn't disturb
- *                        normal operation most of the time because read/write
- *                        requests are relatively fast, and once we are
- *                        performing one tape r/w request, a lot of requests
- *                        from the other device can be queued and ide.c will
- *			  service all of them after this single tape request.
- * Ver 1.0   Dec 11 95   Integrated into Linux 1.3.46 development tree.
- *                       On each read / write request, we now ask the drive
- *                        if we can transfer a constant number of bytes
- *                        (a parameter of the drive) only to its buffers,
- *                        without causing actual media access. If we can't,
- *                        we just wait until we can by polling the DSC bit.
- *                        This ensures that while we are not transferring
- *                        more bytes than the constant referred to above, the
- *                        interrupt latency will not become too high and
- *                        we won't cause an interrupt timeout, as happened
- *                        occasionally in the previous version.
- *                       While polling for DSC, the current request is
- *                        postponed and ide.c is free to handle requests from
- *                        the other device. This is handled transparently to
- *                        ide.c. The hwgroup locking method which was used
- *                        in the previous version was removed.
- *                       Use of new general features which are provided by
- *                        ide.c for use with atapi devices.
- *                        (Programming done by Mark Lord)
- *                       Few potential bug fixes (Again, suggested by Mark)
- *                       Single character device data transfers are now
- *                        not limited in size, as they were before.
- *                       We are asking the tape about its recommended
- *                        transfer unit and send a larger data transfer
- *                        as several transfers of the above size.
- *                        For best results, use an integral number of this
- *                        basic unit (which is shown during driver
- *                        initialization). I will soon add an ioctl to get
- *                        this important parameter.
- *                       Our data transfer buffer is allocated on startup,
- *                        rather than before each data transfer. This should
- *                        ensure that we will indeed have a data buffer.
- * Ver 1.1   Dec 14 95   Fixed random problems which occurred when the tape
- *                        shared an interface with another device.
- *                        (poll_for_dsc was a complete mess).
- *                       Removed some old (non-active) code which had
- *                        to do with supporting buffer cache originated
- *                        requests.
- *                       The block device interface can now be opened, so
- *                        that general ide driver features like the unmask
- *                        interrupts flag can be selected with an ioctl.
- *                        This is the only use of the block device interface.
- *                       New fast pipelined operation mode (currently only on
- *                        writes). When using the pipelined mode, the
- *                        throughput can potentially reach the maximum
- *                        tape supported throughput, regardless of the
- *                        user backup program. On my tape drive, it sometimes
- *                        boosted performance by a factor of 2. Pipelined
- *                        mode is enabled by default, but since it has a few
- *                        downfalls as well, you may want to disable it.
- *                        A short explanation of the pipelined operation mode
- *                        is available below.
- * Ver 1.2   Jan  1 96   Eliminated pipelined mode race condition.
- *                       Added pipeline read mode. As a result, restores
- *                        are now as fast as backups.
- *                       Optimized shared interface behavior. The new behavior
- *                        typically results in better IDE bus efficiency and
- *                        higher tape throughput.
- *                       Pre-calculation of the expected read/write request
- *                        service time, based on the tape's parameters. In
- *                        the pipelined operation mode, this allows us to
- *                        adjust our polling frequency to a much lower value,
- *                        and thus to dramatically reduce our load on Linux,
- *                        without any decrease in performance.
- *                       Implemented additional mtio.h operations.
- *                       The recommended user block size is returned by
- *                        the MTIOCGET ioctl.
- *                       Additional minor changes.
- * Ver 1.3   Feb  9 96   Fixed pipelined read mode bug which prevented the
- *                        use of some block sizes during a restore procedure.
- *                       The character device interface will now present a
- *                        continuous view of the media - any mix of block sizes
- *                        during a backup/restore procedure is supported. The
- *                        driver will buffer the requests internally and
- *                        convert them to the tape's recommended transfer
- *                        unit, making performance almost independent of the
- *                        chosen user block size.
- *                       Some improvements in error recovery.
- *                       By cooperating with ide-dma.c, bus mastering DMA can
- *                        now sometimes be used with IDE tape drives as well.
- *                        Bus mastering DMA has the potential to dramatically
- *                        reduce the CPU's overhead when accessing the device,
- *                        and can be enabled by using hdparm -d1 on the tape's
- *                        block device interface. For more info, read the
- *                        comments in ide-dma.c.
- * Ver 1.4   Mar 13 96   Fixed serialize support.
- * Ver 1.5   Apr 12 96   Fixed shared interface operation, broken in 1.3.85.
- *                       Fixed pipelined read mode inefficiency.
- *                       Fixed nasty null dereferencing bug.
- * Ver 1.6   Aug 16 96   Fixed FPU usage in the driver.
- *                       Fixed end of media bug.
- * Ver 1.7   Sep 10 96   Minor changes for the CONNER CTT8000-A model.
- * Ver 1.8   Sep 26 96   Attempt to find a better balance between good
- *                        interactive response and high system throughput.
- * Ver 1.9   Nov  5 96   Automatically cross encountered filemarks rather
- *                        than requiring an explicit FSF command.
- *                       Abort pending requests at end of media.
- *                       MTTELL was sometimes returning incorrect results.
- *                       Return the real block size in the MTIOCGET ioctl.
- *                       Some error recovery bug fixes.
- * Ver 1.10  Nov  5 96   Major reorganization.
- *                       Reduced CPU overhead a bit by eliminating internal
- *                        bounce buffers.
- *                       Added module support.
- *                       Added multiple tape drives support.
- *                       Added partition support.
- *                       Rewrote DSC handling.
- *                       Some portability fixes.
- *                       Removed ide-tape.h.
- *                       Additional minor changes.
- * Ver 1.11  Dec  2 96   Bug fix in previous DSC timeout handling.
- *                       Use ide_stall_queue() for DSC overlap.
- *                       Use the maximum speed rather than the current speed
- *                        to compute the request service time.
- * Ver 1.12  Dec  7 97   Fix random memory overwriting and/or last block data
- *                        corruption, which could occur if the total number
- *                        of bytes written to the tape was not an integral
- *                        number of tape blocks.
- *                       Add support for INTERRUPT DRQ devices.
- * Ver 1.13  Jan  2 98   Add "speed == 0" work-around for HP COLORADO 5GB
- * Ver 1.14  Dec 30 98   Partial fixes for the Sony/AIWA tape drives.
- *                       Replace cli()/sti() with hwgroup spinlocks.
- * Ver 1.15  Mar 25 99   Fix SMP race condition by replacing hwgroup
- *                        spinlock with private per-tape spinlock.
- * Ver 1.16  Sep  1 99   Add OnStream tape support.
- *                       Abort read pipeline on EOD.
- *                       Wait for the tape to become ready in case it returns
- *                        "in the process of becoming ready" on open().
- *                       Fix zero padding of the last written block in
- *                        case the tape block size is larger than PAGE_SIZE.
- *                       Decrease the default disconnection time to tn.
- * Ver 1.16e Oct  3 99   Minor fixes.
- * Ver 1.16e1 Oct 13 99  Patches by Arnold Niessen,
- *                          niessen@iae.nl / arnold.niessen@philips.com
- *                   GO-1)  Undefined code in idetape_read_position
- *				according to Gadi's email
- *                   AJN-1) Minor fix asc == 11 should be asc == 0x11
- *                               in idetape_issue_packet_command (did effect
- *                               debugging output only)
- *                   AJN-2) Added more debugging output, and
- *                              added ide-tape: where missing. I would also
- *				like to add tape->name where possible
- *                   AJN-3) Added different debug_level's 
- *                              via /proc/ide/hdc/settings
- * 				"debug_level" determines amount of debugging output;
- * 				can be changed using /proc/ide/hdx/settings
- * 				0 : almost no debugging output
- * 				1 : 0+output errors only
- * 				2 : 1+output all sensekey/asc
- * 				3 : 2+follow all chrdev related procedures
- * 				4 : 3+follow all procedures
- * 				5 : 4+include pc_stack rq_stack info
- * 				6 : 5+USE_COUNT updates
- *                   AJN-4) Fixed timeout for retension in idetape_queue_pc_tail
- *				from 5 to 10 minutes
- *                   AJN-5) Changed maximum number of blocks to skip when
- *                              reading tapes with multiple consecutive write
- *                              errors from 100 to 1000 in idetape_get_logical_blk
- *                   Proposed changes to code:
- *                   1) output "logical_blk_num" via /proc
- *                   2) output "current_operation" via /proc
- *                   3) Either solve or document the fact that `mt rewind' is
- *                      required after reading from /dev/nhtx to be
- *			able to rmmod the idetape module;
- *			Also, sometimes an application finishes but the
- *			device remains `busy' for some time. Same cause ?
- *                   Proposed changes to release-notes:
- *		     4) write a simple `quickstart' section in the
- *                      release notes; I volunteer if you don't want to
- * 		     5) include a pointer to video4linux in the doc
- *                      to stimulate video applications
- *                   6) release notes lines 331 and 362: explain what happens
- *			if the application data rate is higher than 1100 KB/s; 
- *			similar approach to lower-than-500 kB/s ?
- *		     7) 6.6 Comparison; wouldn't it be better to allow different 
- *			strategies for read and write ?
- *			Wouldn't it be better to control the tape buffer
- *			contents instead of the bandwidth ?
- *		     8) line 536: replace will by would (if I understand
- *			this section correctly, a hypothetical and unwanted situation
- *			 is being described)
- * Ver 1.16f Dec 15 99   Change place of the secondary OnStream header frames.
- * Ver 1.17  Nov 2000 / Jan 2001  Marcel Mol, marcel@mesa.nl
- *			- Add idetape_onstream_mode_sense_tape_parameter_page
- *			  function to get tape capacity in frames: tape->capacity.
- *			- Add support for DI-50 drives( or any DI- drive).
- *			- 'workaround' for read error/blank block arround block 3000.
- *			- Implement Early warning for end of media for Onstream.
- *			- Cosmetic code changes for readability.
- *			- Idetape_position_tape should not use SKIP bit during
- *			  Onstream read recovery.
- *			- Add capacity, logical_blk_num and first/last_frame_position
- *			  to /proc/ide/hd?/settings.
- *			- Module use count was gone in the Linux 2.4 driver.
- * Ver 1.17a Apr 2001 Willem Riede osst@riede.org
- * 			- Get drive's actual block size from mode sense block descriptor
- * 			- Limit size of pipeline
- *
- * Here are some words from the first releases of hd.c, which are quoted
- * in ide.c and apply here as well:
- *
- * | Special care is recommended.  Have Fun!
- *
- */
-
-/*
- * An overview of the pipelined operation mode.
- *
- * In the pipelined write mode, we will usually just add requests to our
- * pipeline and return immediately, before we even start to service them. The
- * user program will then have enough time to prepare the next request while
- * we are still busy servicing previous requests. In the pipelined read mode,
- * the situation is similar - we add read-ahead requests into the pipeline,
- * before the user even requested them.
- *
- * The pipeline can be viewed as a "safety net" which will be activated when
- * the system load is high and prevents the user backup program from keeping up
- * with the current tape speed. At this point, the pipeline will get
- * shorter and shorter but the tape will still be streaming at the same speed.
- * Assuming we have enough pipeline stages, the system load will hopefully
- * decrease before the pipeline is completely empty, and the backup program
- * will be able to "catch up" and refill the pipeline again.
- * 
- * When using the pipelined mode, it would be best to disable any type of
- * buffering done by the user program, as ide-tape already provides all the
- * benefits in the kernel, where it can be done in a more efficient way.
- * As we will usually not block the user program on a request, the most
- * efficient user code will then be a simple read-write-read-... cycle.
- * Any additional logic will usually just slow down the backup process.
- *
- * Using the pipelined mode, I get a constant over 400 KBps throughput,
- * which seems to be the maximum throughput supported by my tape.
- *
- * However, there are some downfalls:
- *
- *	1.	We use memory (for data buffers) in proportional to the number
- *		of pipeline stages (each stage is about 26 KB with my tape).
- *	2.	In the pipelined write mode, we cheat and postpone error codes
- *		to the user task. In read mode, the actual tape position
- *		will be a bit further than the last requested block.
- *
- * Concerning (1):
- *
- *	1.	We allocate stages dynamically only when we need them. When
- *		we don't need them, we don't consume additional memory. In
- *		case we can't allocate stages, we just manage without them
- *		(at the expense of decreased throughput) so when Linux is
- *		tight in memory, we will not pose additional difficulties.
- *
- *	2.	The maximum number of stages (which is, in fact, the maximum
- *		amount of memory) which we allocate is limited by the compile
- *		time parameter IDETAPE_MAX_PIPELINE_STAGES.
- *
- *	3.	The maximum number of stages is a controlled parameter - We
- *		don't start from the user defined maximum number of stages
- *		but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
- *		will not even allocate this amount of stages if the user
- *		program can't handle the speed). We then implement a feedback
- *		loop which checks if the pipeline is empty, and if it is, we
- *		increase the maximum number of stages as necessary until we
- *		reach the optimum value which just manages to keep the tape
- *		busy with minimum allocated memory or until we reach
- *		IDETAPE_MAX_PIPELINE_STAGES.
- *
- * Concerning (2):
- *
- *	In pipelined write mode, ide-tape can not return accurate error codes
- *	to the user program since we usually just add the request to the
- *      pipeline without waiting for it to be serviced. In case an error
- *      occurs, I will report it on the next user request.
- *
- *	In the pipelined read mode, subsequent read requests or forward
- *	filemark spacing will perform correctly, as we preserve all blocks
- *	and filemarks which we encountered during our excess read-ahead.
- * 
- *	For accurate tape positioning and error reporting, disabling
- *	pipelined mode might be the best option.
- *
- * You can enable/disable/tune the pipelined operation mode by adjusting
- * the compile time parameters below.
- */
-
-/*
- *	Possible improvements.
- *
- *	1.	Support for the ATAPI overlap protocol.
- *
- *		In order to maximize bus throughput, we currently use the DSC
- *		overlap method which enables ide.c to service requests from the
- *		other device while the tape is busy executing a command. The
- *		DSC overlap method involves polling the tape's status register
- *		for the DSC bit, and servicing the other device while the tape
- *		isn't ready.
- *
- *		In the current QIC development standard (December 1995),
- *		it is recommended that new tape drives will *in addition* 
- *		implement the ATAPI overlap protocol, which is used for the
- *		same purpose - efficient use of the IDE bus, but is interrupt
- *		driven and thus has much less CPU overhead.
- *
- *		ATAPI overlap is likely to be supported in most new ATAPI
- *		devices, including new ATAPI cdroms, and thus provides us
- *		a method by which we can achieve higher throughput when
- *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
+ * Oct 1999		Arnold Niessen, <niessen@iae.nl>, <arnold.niessen@philips.com>
+ * Nov 2000, Jan 2001	Marcel Mol,	<marcel@mesa.nl>
+ * Apr 2001		Willem Riede,	<osst@riede.org>
  */
 
-#define IDETAPE_VERSION "1.17a"
+/*
+ * FIXME: clean tape->spinlock locking  --bzolnier
+ */
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -419,9 +36,11 @@
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
 #include <linux/completion.h>
+#include <linux/buffer_head.h>
+#include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/atapi.h>
-#include <linux/buffer_head.h>
+#include <linux/delay.h>
 
 #include <asm/byteorder.h>
 #include <asm/irq.h>
@@ -445,6 +64,7 @@
 
 #define OS_DATA_STARTFRAME1	20
 #define OS_DATA_ENDFRAME1	2980
+
 /*
  * partition
  */
@@ -1249,7 +869,7 @@
 	}
 }
 
-char *idetape_command_key_verbose (byte idetape_command_key)
+char *idetape_command_key_verbose(u8 idetape_command_key)
 {
 	switch (idetape_command_key) {
 		case IDETAPE_TEST_UNIT_READY_CMD:	return("TEST_UNIT_READY_CMD");
@@ -1439,7 +1059,7 @@
 # if IDETAPE_DEBUG_LOG_VERBOSE
 	if (tape->debug_level >= 1)
 		printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n",
-			idetape_command_key_verbose((byte) pc->c[0]),
+			idetape_command_key_verbose(pc->c[0]),
 			result->sense_key,
 			result->asc,
 			result->ascq);
@@ -1448,7 +1068,8 @@
 
 	if (tape->onstream && result->sense_key == 2 && result->asc == 0x53 && result->ascq == 2) {
 		clear_bit(PC_DMA_ERROR, &pc->flags);
-		ide_stall_queue(drive, HZ / 2);
+		/* FIXME: we should use timeouts here */
+		mdelay(HZ / 2 * 1000);
 		return;
 	}
 #ifdef CONFIG_BLK_DEV_IDEDMA
@@ -1815,7 +1436,8 @@
 		printk(KERN_INFO "ide-tape: idetape_postpone_request\n");
 #endif
 	tape->postponed_rq = rq;
-	ide_stall_queue(drive, tape->dsc_polling_frequency);
+	/* FIXME: we should use timeouts here */
+	mdelay(tape->dsc_polling_frequency * 1000);
 }
 
 /*
@@ -2166,7 +1788,7 @@
 /*
  *	A mode sense command is used to "sense" tape parameters.
  */
-static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, byte page_code)
+static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, u8 page_code)
 {
 	atapi_init_pc(pc);
 	pc->c[0] = IDETAPE_MODE_SENSE_CMD;
@@ -3225,7 +2847,7 @@
  *	of the request queue and wait for their completion.
  *
  */
-static int idetape_position_tape(struct ata_device *drive, unsigned int block, byte partition, int skip)
+static int idetape_position_tape(struct ata_device *drive, unsigned int block, u8 partition, int skip)
 {
 	idetape_tape_t *tape = drive->driver_data;
 	int retval;
@@ -3981,7 +3603,7 @@
 		printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
 		bytes_read=blocks*tape->tape_block_size;
 	}
-#endif /* IDETAPE_DEBUG_BUGS */
+#endif
 	return (bytes_read);
 }
 
@@ -5892,18 +5514,17 @@
 	int minor = tape->minor;
 	unsigned long flags;
 
-	save_flags (flags);	/* all CPUs (overkill?) */
-	cli();			/* all CPUs (overkill?) */
+	spin_lock_irqsave (&tape->spinlock, flags);	/* overkill? */
 	if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) {
-		restore_flags(flags);	/* all CPUs (overkill?) */
+		spin_unlock_irqrestore(&tape->spinlock, flags);
 		return 1;
 	}
 	idetape_chrdevs[minor].drive = NULL;
-	restore_flags (flags);	/* all CPUs (overkill?) */
+	spin_unlock_irqrestore(&tape->spinlock, flags);
 
 	MOD_DEC_USE_COUNT;
 
-	ide_unregister_subdriver (drive);
+	ata_unregister_device(drive);
 	drive->driver_data = NULL;
 	devfs_unregister (tape->de_r);
 	devfs_unregister (tape->de_n);
@@ -5911,7 +5532,7 @@
 	for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++)
 		if (idetape_chrdevs[minor].drive != NULL)
 			return 0;
-	devfs_unregister_chrdev (IDETAPE_MAJOR, "ht");
+	unregister_chrdev (IDETAPE_MAJOR, "ht");
 	idetape_chrdev_present = 0;
 	return 0;
 }
@@ -5973,7 +5594,7 @@
 			idetape_chrdevs[minor].drive = NULL;
 
 	if (!idetape_chrdev_present &&
-	    devfs_register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) {
+	    register_chrdev (IDETAPE_MAJOR, "ht", &idetape_fops)) {
 		printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
 		return;
 	}
@@ -5992,11 +5613,11 @@
 	}
 	tape = (idetape_tape_t *) kmalloc (sizeof (idetape_tape_t), GFP_KERNEL);
 	if (!tape) {
-		printk (KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
+		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
 		return;
 	}
-	if (ide_register_subdriver (drive, &idetape_driver)) {
-		printk (KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
+	if (ata_register_device(drive, &idetape_driver)) {
+		printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
 		kfree (tape);
 		return;
 	}
@@ -6017,7 +5638,7 @@
 	supported++;
 
 	if (!idetape_chrdev_present && !supported) {
-		devfs_unregister_chrdev (IDETAPE_MAJOR, "ht");
+		unregister_chrdev (IDETAPE_MAJOR, "ht");
 	} else
 		idetape_chrdev_present = 1;
 
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/ide/ide.c	Thu Aug  1 14:17:41 2002
@@ -481,12 +481,9 @@
 		udelay(1);
 		ata_irq_enable(drive, 0);
 
-		/* This command actually looks suspicious, since I couldn't
-		 * find it in any standard document.
-		 */
 		OUT_BYTE(0x04, ch->io_ports[IDE_CONTROL_OFFSET]);
 		udelay(10);
-		OUT_BYTE(WIN_NOP, ch->io_ports[IDE_CONTROL_OFFSET]);
+		OUT_BYTE(0x00, ch->io_ports[IDE_CONTROL_OFFSET]);
 		ret = ata_status_poll(drive, 0, BUSY_STAT, WAIT_WORSTCASE, NULL);
 		ata_mask(drive);
 
@@ -503,138 +500,86 @@
 }
 
 /*
- * This is used by a drive to give excess bandwidth back by sleeping for
- * timeout jiffies.
- */
-void ide_stall_queue(struct ata_device *drive, unsigned long timeout)
-{
-	if (timeout > WAIT_WORSTCASE)
-		timeout = WAIT_WORSTCASE;
-	drive->sleep = timeout + jiffies;
-}
-
-/*
  * Issue a new request.
  * Caller must have already done spin_lock_irqsave(channel->lock, ...)
  */
 void do_ide_request(request_queue_t *q)
 {
-	struct ata_channel *channel = q->queuedata;
+	struct ata_device *drive = q->queuedata;
+	struct ata_channel *ch = drive->channel;
 
-	while (!test_and_set_bit(IDE_BUSY, channel->active)) {
-		struct ata_channel *ch;
-		struct ata_device *drive = NULL;
+	while (!test_and_set_bit(IDE_BUSY, ch->active)) {
 		unsigned int unit;
 		ide_startstop_t ret;
 
-		/*
-		 * Select the next device which will be serviced.  This selects
-		 * only between devices on the same channel, since everything
-		 * else will be scheduled on the queue level.
-		 */
-
-		for (unit = 0; unit < MAX_DRIVES; ++unit) {
-			struct ata_device *tmp = &channel->drives[unit];
-
-			if (!tmp->present)
-				continue;
-
-			/* There are no requests pending for this device.
-			 */
-			if (blk_queue_empty(&tmp->queue))
-				continue;
-
-
-			/* This device still wants to remain idle.
-			 */
-			if (tmp->sleep && time_after(tmp->sleep, jiffies))
-				continue;
-
-			/* Take this device, if there is no device choosen thus
-			 * far or which is more urgent.
-			 */
-			if (!drive || (tmp->sleep && (!drive->sleep || time_after(drive->sleep, tmp->sleep)))) {
-				if (!blk_queue_plugged(&tmp->queue))
-					drive = tmp;
-			}
+		if (drive) {
+			/* No request pending?! */
+			if (blk_queue_empty(&drive->queue))
+				drive = NULL;
+			/* Still resorting requests?! */
+			else if (blk_queue_plugged(&drive->queue))
+				drive = NULL;
 		}
 
 		if (!drive) {
-			unsigned long sleep = 0;
-
+			/* We should never get here! */
+			/* Unless someone called us from IRQ context after
+			 * finishing the actual request already. (Shrug!)
+			 */
+			// printk(KERN_INFO "no device found!\n");
 			for (unit = 0; unit < MAX_DRIVES; ++unit) {
-				struct ata_device *tmp = &channel->drives[unit];
+				struct ata_device *tmp = &ch->drives[unit];
 
 				if (!tmp->present)
 					continue;
 
-				/* This device is sleeping and waiting to be serviced
-				 * earlier than any other device we checked thus far.
+				/* There are no requests pending for this
+				 * device.
 				 */
-				if (tmp->sleep && (!sleep || time_after(sleep, tmp->sleep)))
-					sleep = tmp->sleep;
-			}
+				if (blk_queue_empty(&tmp->queue))
+					continue;
 
-			if (sleep) {
-				/*
-				 * Take a short snooze, and then wake up again.  Just
-				 * in case there are big differences in relative
-				 * throughputs.. don't want to hog the cpu too much.
+				/* Take this device, if there is no device
+				 * choosen thus far and the queue is ready for
+				 * processing.
 				 */
+				if (!drive && !blk_queue_plugged(&tmp->queue))
+					drive = tmp;
+			}
+		}
 
-				if (time_after(jiffies, sleep - WAIT_MIN_SLEEP))
-					sleep = jiffies + WAIT_MIN_SLEEP;
-#if 1
-				if (timer_pending(&channel->timer))
-					printk(KERN_ERR "%s: timer already active\n", __FUNCTION__);
-#endif
-				set_bit(IDE_SLEEP, channel->active);
-				mod_timer(&channel->timer, sleep);
+		if (!drive) {
+			/* Ugly, but how can we sleep for the lock otherwise?
+			 */
 
-				/*
-				 * We purposely leave us busy while sleeping becouse we
-				 * are prepared to handle the IRQ from it.
-				 *
-				 * FIXME: Make sure sleeping can't interferre with
-				 * operations of other devices on the same channel.
-				 */
-			} else {
-				/* FIXME: use queue plugging instead of active to block
-				 * upper layers from stomping on us */
-				/* Ugly, but how can we sleep for the lock otherwise?
-				 * */
-
-				ide_release_lock(&ide_irq_lock);/* for atari only */
-				clear_bit(IDE_BUSY, channel->active);
-
-				/* All requests are done.
-				 *
-				 * Disable IRQs from the last drive on this channel, to
-				 * make sure that it wan't throw stones at us when we
-				 * are not prepared to take them.
-				 */
+			ide_release_lock(&ide_irq_lock);/* for atari only */
+			clear_bit(IDE_BUSY, ch->active);
 
-				if (channel->drive && !channel->drive->using_tcq)
-					ata_irq_enable(channel->drive, 0);
-			}
+			/* All requests are done.
+			 *
+			 * Disable IRQs from the last drive on this channel, to
+			 * make sure that it wan't throw stones at us when we
+			 * are not prepared to take them.
+			 */
+
+			if (ch->drive && !ch->drive->using_tcq)
+				ata_irq_enable(ch->drive, 0);
 
 			return;
 		}
 
 		/* Remember the last drive we where acting on.
 		 */
-		ch = drive->channel;
 		ch->drive = drive;
 
 		/* Feed commands to a drive until it barfs.
 		 */
 		do {
 			struct request *rq = NULL;
-			sector_t block;
 
-			/* Abort early if we can't queue another command. for non tcq,
-			 * ata_can_queue is always 1 since we never get here unless the
-			 * drive is idle.
+			/* Abort early if we can't queue another command. for
+			 * non tcq, ata_can_queue is always 1 since we never
+			 * get here unless the drive is idle.
 			 */
 
 			if (!ata_can_queue(drive)) {
@@ -646,18 +591,16 @@
 				break;
 			}
 
-			drive->sleep = 0;
-
 			if (test_bit(IDE_DMA, ch->active)) {
 				printk(KERN_ERR "%s: error: DMA in progress...\n", drive->name);
 				break;
 			}
 
-			/* There's a small window between where the queue could be
-			 * replugged while we are in here when using tcq (in which case
-			 * the queue is probably empty anyways...), so check and leave
-			 * if appropriate. When not using tcq, this is still a severe
-			 * BUG!
+			/* There's a small window between where the queue could
+			 * be replugged while we are in here when using tcq (in
+			 * which case the queue is probably empty anyways...),
+			 * so check and leave if appropriate. When not using
+			 * tcq, this is still a severe BUG!
 			 */
 
 			if (blk_queue_plugged(&drive->queue)) {
@@ -692,30 +635,12 @@
 			/*
 			 * This initiates handling of a new I/O request.
 			 */
-
 			BUG_ON(!(rq->flags & REQ_STARTED));
 
-#ifdef DEBUG
-			printk("%s: %s: current=0x%08lx\n", ch->name, __FUNCTION__, (unsigned long) rq);
-#endif
-
 			/* bail early if we've exceeded max_failures */
 			if (drive->max_failures && (drive->failures > drive->max_failures))
 				goto kill_rq;
 
-			block = rq->sector;
-
-			/* Strange disk manager remap.
-			 */
-			if (rq->flags & REQ_CMD)
-				if (drive->type == ATA_DISK || drive->type == ATA_FLOPPY)
-					block += drive->sect0;
-
-			/* Yecch - this will shift the entire interval, possibly killing some
-			 * innocent following sector.
-			 */
-			if (block == 0 && drive->remap_0_to_1 == 1)
-				block = 1;  /* redirect MBR access to EZ-Drive partn table */
 
 			ata_select(drive, 0);
 			ret = ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
@@ -737,9 +662,9 @@
 			 * handler down to the device type driver.
 			 */
 
-			if (ata_ops(drive)->do_request) {
-				ret = ata_ops(drive)->do_request(drive, rq, block);
-			} else {
+			if (ata_ops(drive)->do_request)
+				ret = ata_ops(drive)->do_request(drive, rq, rq->sector);
+			else {
 kill_rq:
 				if (ata_ops(drive) && ata_ops(drive)->end_request)
 					ata_ops(drive)->end_request(drive, rq, 0);
@@ -749,12 +674,8 @@
 
 			}
 			spin_lock_irq(ch->lock);
-
 			/* continue if command started, so we are busy */
 		} while (ret != ATA_OP_CONTINUES);
-		/* make sure the BUSY bit is set */
-		/* FIXME: perhaps there is some place where we miss to set it? */
-		//		set_bit(IDE_BUSY, ch->active);
 	}
 }
 
@@ -1200,6 +1121,5 @@
 EXPORT_SYMBOL(ata_error);
 
 EXPORT_SYMBOL(ata_end_request);
-EXPORT_SYMBOL(ide_stall_queue);
 
 EXPORT_SYMBOL(ide_setup_ports);
diff -Nru a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c
--- a/drivers/ide/ioctl.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/ide/ioctl.c	Thu Aug  1 14:17:39 2002
@@ -33,6 +33,15 @@
 
 #include "ioctl.h"
 
+
+/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */
+struct hd_big_geometry {
+	u8 heads;
+	u8 sectors;
+	u32 cylinders;
+	unsigned long start;
+};
+
 /*
  * Implement generic ioctls invoked from userspace to imlpement specific
  * functionality.
diff -Nru a/drivers/ide/it8172.c b/drivers/ide/it8172.c
--- a/drivers/ide/it8172.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/it8172.c	Thu Aug  1 14:17:36 2002
@@ -89,10 +89,7 @@
 	    drive_enables |= 0x0006;
     }
 
-    save_flags(flags);
-    cli();
 	pci_write_config_word(dev, master_port, master_data);
-    restore_flags(flags);
 }
 
 #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_IT8172_TUNING)
diff -Nru a/drivers/ide/main.c b/drivers/ide/main.c
--- a/drivers/ide/main.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/main.c	Thu Aug  1 14:17:36 2002
@@ -176,22 +176,34 @@
 	};
 
 	unsigned int unit;
-	hw_regs_t hw;
 
 	/* bulk initialize channel & drive info with zeros */
 	memset(ch, 0, sizeof(struct ata_channel));
-	memset(&hw, 0, sizeof(hw_regs_t));
 
 	/* fill in any non-zero initial values */
 	ch->index = index;
-	ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, &ch->irq);
+	ide_init_hwif_ports(&ch->hw, ide_default_io_base(index), 0, &ch->irq);
 
-	memcpy(&ch->hw, &hw, sizeof(hw));
-	memcpy(ch->io_ports, hw.io_ports, sizeof(hw.io_ports));
+	memcpy(ch->io_ports, ch->hw.io_ports, sizeof(ch->hw.io_ports));
+
+	/* Most controllers cannot do transfers across 64kB boundaries.
+	   trm290 can do transfers within a 4GB boundary, so it changes
+	   this mask accordingly. */
+	ch->seg_boundary_mask = 0xffff;
+
+	/* Some chipsets (cs5530, any others?) think a 64kB transfer
+	   is 0 byte transfer, so set the limit one sector smaller.
+	   In the future, we may default to 64kB transfers and let
+	   invidual chipsets with this problem change ch->max_segment_size. */
+	ch->max_segment_size = (1<<16) - 512;
 
 	ch->noprobe	= !ch->io_ports[IDE_DATA_OFFSET];
 #ifdef CONFIG_BLK_DEV_HD
-	if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
+
+	/* Ignore disks for which handling by the legacy driver was requested
+	 * by the used.
+	 */
+	if (ch->io_ports[IDE_DATA_OFFSET] == 0x1f0)
 		ch->noprobe = 1; /* may be overridden by ide_setup() */
 #endif
 
@@ -361,7 +373,7 @@
 				if (ata_ops(drive)->cleanup(drive))
 					goto abort;
 			} else
-				ide_unregister_subdriver(drive);
+				ata_unregister_device(drive);
 		}
 	}
 	ch->present = 0;
@@ -476,17 +488,19 @@
 	blk_dev[ch->major].data = NULL;
 	blk_dev[ch->major].queue = NULL;
 	blk_clear(ch->major);
-	gd = ch->gd;
+	gd = ch->gd[0];
 	if (gd) {
-		del_gendisk(gd);
-		kfree(gd->sizes);
+		int i;
+		for (i = 0; i < MAX_DRIVES; i++)
+			del_gendisk(gd + i);
 		kfree(gd->part);
 		if (gd->de_arr)
 			kfree (gd->de_arr);
 		if (gd->flags)
 			kfree (gd->flags);
 		kfree(gd);
-		ch->gd = NULL;
+		for (i = 0; i < MAX_DRIVES; i++)
+			ch->gd[i] = NULL;
 	}
 
 	/*
@@ -701,79 +715,46 @@
 
 /*
  * This gets called VERY EARLY during initialization, to handle kernel "command
- * line" strings beginning with "hdx=" or "ide".It gets called even before the
- * actual module gets initialized.
+ * line" strings beginning with "hdx=".  It gets called even before the actual
+ * module gets initialized.
  *
  * Please look at Documentation/ide.txt to see the complete list of supported
  * options.
  */
-int __init ide_setup(char *s)
+static int __init ata_hd_setup(char *s)
 {
-	int i, vals[4];
-	struct ata_channel *ch;
+	int vals[4];
+	struct ata_channel *ch;	/* FIXME:  Channel parms should not be accessed in ata_hd_setup */
 	struct ata_device *drive;
 	unsigned int hw, unit;
 	const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
-	const char max_ch  = '0' + (MAX_HWIFS - 1);
-
-	if (!strncmp(s, "hd=", 3))	/* hd= is for hd.c driver and not us */
-		return 0;
 
-	if (strncmp(s,"ide",3) &&
-	    strncmp(s,"hd",2))		/* hdx= & hdxlun= */
+	if (s[0] == '=')	/* hd= is for hd.c driver and not us */
 		return 0;
 
-	printk(KERN_INFO  "ide_setup: %s", s);
+	printk(KERN_INFO  "hd%s", s);
 	init_global_data();
 
-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
-	if (!strcmp(s, "ide=doubler")) {
-		extern int ide_doubler;
-
-		printk(KERN_INFO" : Enabled support for IDE doublers\n");
-		ide_doubler = 1;
-
-		return 1;
-	}
-#endif
-
-	if (!strcmp(s, "ide=nodma")) {
-		printk(KERN_INFO "ATA: Prevented DMA\n");
-		noautodma = 1;
-
-		return 1;
-	}
-
-#ifdef CONFIG_PCI
-	if (!strcmp(s, "ide=reverse")) {
-		ide_scan_direction = 1;
-		printk(" : Enabled support for IDE inverse scan order.\n");
-
-		return 1;
-	}
-#endif
-
-	/*
-	 * Look for drive options:  "hdx="
-	 */
-	if (!strncmp(s, "hd", 2) && s[2] >= 'a' && s[2] <= max_drive) {
-		const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
+	if (s[0] >= 'a' && s[0] <= max_drive) {
+		static const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
 				"serialize", "autotune", "noautotune",
-				"slow", "flash", "remap", "noremap", "scsi", NULL};
-		unit = s[2] - 'a';
+				"slow", "flash", "scsi", NULL};
+		unit = s[0] - 'a';
 		hw   = unit / MAX_DRIVES;
 		unit = unit % MAX_DRIVES;
 		ch = &ide_hwifs[hw];
 		drive = &ch->drives[unit];
-		if (!strncmp(s+3, "=ide-", 5)) {
-			strncpy(drive->driver_req, s + 4, 9);
+
+		/* Look for hdx=ide-* */
+		if (!strncmp(s+1, "=ide-", 5)) {
+			strncpy(drive->driver_req, s+2, 9);
 			goto done;
 		}
 		/*
 		 * Look for last lun option:  "hdxlun="
 		 */
-		if (!strncmp(s+3, "lun=", 4)) {
-	                if (*get_options(s+7, 2, vals) || vals[0]!=1)
+		if (!strncmp(s+1, "lun=", 4)) {
+	                if (*get_options(s+5, 2, vals) || vals[0]!=1)
 				goto bad_option;
 			if (vals[1] >= 0 && vals[1] <= 7) {
 				drive->last_lun = vals[1];
@@ -782,7 +763,7 @@
 				printk(" -- BAD LAST LUN! Expected value from 0 to 7");
 			goto done;
 		}
-		switch (match_parm(s+3, hd_words, vals, 3)) {
+		switch (match_parm(s+1, hd_words, vals, 3)) {
 			case -1: /* "none" */
 				drive->nobios = 1;  /* drop into "noprobe" */
 			case -2: /* "noprobe" */
@@ -790,16 +771,16 @@
 				goto done;
 			case -3: /* "nowerr" */
 				drive->bad_wstat = BAD_R_STAT;
-				ch->noprobe = 0;
+				ch->noprobe = 0;	/* FIXME:  Channel parm */
 				goto done;
 			case -4: /* "cdrom" */
 				drive->present = 1;
 				drive->type = ATA_ROM;
-				ch->noprobe = 0;
+				ch->noprobe = 0;	/* FIXME:  Channel parm */
 				goto done;
 			case -5: /* "serialize" */
 				printk(" -- USE \"ide%d=serialize\" INSTEAD", hw);
-				goto do_serialize;
+				goto bad_option;
 			case -6: /* "autotune" */
 				drive->autotune = 1;
 				goto done;
@@ -807,18 +788,12 @@
 				drive->autotune = 2;
 				goto done;
 			case -8: /* "slow" */
-				ch->slow = 1;
+				ch->slow = 1;		/* FIXME:  Channel parm */
 				goto done;
 			case -9: /* "flash" */
 				drive->ata_flash = 1;
 				goto done;
-			case -10: /* "remap" */
-				drive->remap_0_to_1 = 1;
-				goto done;
-			case -11: /* "noremap" */
-				drive->remap_0_to_1 = 2;
-				goto done;
-			case -12: /* "scsi" */
+			case -10: /* "scsi" */
 #if defined(CONFIG_BLK_DEV_IDESCSI) && defined(CONFIG_SCSI)
 				drive->scsi = 1;
 				goto done;
@@ -840,11 +815,63 @@
 		}
 	}
 
+bad_option:
+	printk(" -- BAD OPTION\n");
+	return 1;
+
+done:
+	printk("\n");
+
+	return 1;
+}
+
+/*
+ * This gets called VERY EARLY during initialization, to handle kernel "command
+ * line" strings beginning with "ide".  It gets called even before the actual
+ * module gets initialized.
+ *
+ * Please look at Documentation/ide.txt to see the complete list of supported
+ * options.
+ */
+int __init ide_setup(char *s)
+{
+	int i, vals[4];
+	struct ata_channel *ch;
+	unsigned int hw;
+	const char max_ch  = '0' + (MAX_HWIFS - 1);
+
+	printk(KERN_INFO  "ide%s", s);
+	init_global_data();
+
+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+	if (!strcmp(s, "=doubler")) {
+		extern int ide_doubler;
+
+		printk(KERN_INFO" : Enabled support for ATA doublers\n");
+		ide_doubler = 1;
+		return 1;
+	}
+#endif
+
+	if (!strcmp(s, "=nodma")) {
+		printk(KERN_INFO "ATA: Prevented DMA\n");
+		noautodma = 1;
+		return 1;
+	}
+
+#ifdef CONFIG_PCI
+	if (!strcmp(s, "=reverse")) {
+		ide_scan_direction = 1;
+		printk(" : Enabled support for IDE inverse scan order.\n");
+		return 1;
+	}
+#endif
+
 	/*
 	 * Look for bus speed option:  "idebus="
 	 */
-	if (!strncmp(s, "idebus=", 7)) {
-		if (*get_options(s+7, 2, vals) || vals[0] != 1)
+	if (!strncmp(s, "bus=", 4)) {
+		if (*get_options(s+4, 2, vals) || vals[0] != 1)
 			goto bad_option;
 		idebus_parameter = vals[1];
 		goto done;
@@ -853,7 +880,7 @@
 	/*
 	 * Look for interface options:  "idex="
 	 */
-	if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) {
+	if (s[0] >= '0' && s[0] <= max_ch) {
 		/*
 		 * Be VERY CAREFUL changing this: note hardcoded indexes below
 		 */
@@ -861,11 +888,11 @@
 			"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL };
 		const char *ide_words[] = {
 			"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
-		hw = s[3] - '0';
+		hw = s[0] - '0';
 		ch = &ide_hwifs[hw];
 
 
-		switch (match_parm(s+4, ide_options, vals, 1)) {
+		switch (match_parm(s + 1, ide_options, vals, 1)) {
 			case -7: /* ata66 */
 #ifdef CONFIG_PCI
 				ch->udma_four = 1;
@@ -889,7 +916,6 @@
 				ch->drives[1].autotune = 1;
 				goto done;
 			case -2: /* "serialize" */
-			do_serialize:
 				{
 					struct ata_channel *mate;
 
@@ -904,7 +930,10 @@
 				goto done;
 		}
 
-		i = match_parm(&s[4], ide_words, vals, 3);
+		/*
+		 * Check for specific chipset name
+		 */
+		i = match_parm(s + 1, ide_words, vals, 3);
 
 		/*
 		 * Cryptic check to ensure chipset not already set for a channel:
@@ -913,7 +942,7 @@
 			if (ide_hwifs[hw].chipset != ide_unknown)
 				goto bad_option;	/* chipset already specified */
 			if (i != -7 && hw != 0)
-				goto bad_channel;		/* chipset drivers are for "ide0=" only */
+				goto bad_channel;	/* chipset drivers are for "ide0=" only */
 			if (i != -7 && ide_hwifs[1].chipset != ide_unknown)
 				goto bad_option;	/* chipset for 2nd port already specified */
 			printk("\n");
@@ -931,7 +960,7 @@
 #ifdef CONFIG_BLK_DEV_ALI14XX
 			case -6:  /* "ali14xx" */
 			{
-				extern void init_ali14xx (void);
+				extern void init_ali14xx(void);
 				init_ali14xx();
 				goto done;
 			}
@@ -939,7 +968,7 @@
 #ifdef CONFIG_BLK_DEV_UMC8672
 			case -5:  /* "umc8672" */
 			{
-				extern void init_umc8672 (void);
+				extern void init_umc8672(void);
 				init_umc8672();
 				goto done;
 			}
@@ -947,7 +976,7 @@
 #ifdef CONFIG_BLK_DEV_DTC2278
 			case -4:  /* "dtc2278" */
 			{
-				extern void init_dtc2278 (void);
+				extern void init_dtc2278(void);
 				init_dtc2278();
 				goto done;
 			}
@@ -963,7 +992,7 @@
 #ifdef CONFIG_BLK_DEV_HT6560B
 			case -2:  /* "ht6560b" */
 			{
-				extern void init_ht6560b (void);
+				extern void init_ht6560b(void);
 				init_ht6560b();
 				goto done;
 			}
@@ -971,7 +1000,7 @@
 #if CONFIG_BLK_DEV_QD65XX
 			case -1:  /* "qd65xx" */
 			{
-				extern void init_qd65xx (void);
+				extern void init_qd65xx(void);
 				init_qd65xx();
 				goto done;
 			}
@@ -1012,10 +1041,7 @@
 
 /****************************************************************************/
 
-/*
- * This is in fact registering a device not a driver.
- */
-int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driver)
+int ata_register_device(struct ata_device *drive, struct ata_operations *driver)
 {
 	unsigned long flags;
 
@@ -1027,12 +1053,9 @@
 		return 1;
 	}
 
-	/* FIXME: This will be pushed to the drivers! Thus allowing us to
-	 * save one parameter here and to separate this out.
-	 */
 	drive->driver = driver;
-
 	spin_unlock_irqrestore(&ide_lock, flags);
+
 	/* Default autotune or requested autotune */
 	if (drive->autotune != 2) {
 		struct ata_channel *ch = drive->channel;
@@ -1046,11 +1069,13 @@
 			 *   PARANOIA!!!
 			 */
 
+			spin_lock_irqsave(ch->lock, flags);
 			udma_enable(drive, 0, 0);
 			ch->udma_setup(drive, ch->modes_map);
 #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT
 			udma_tcq_enable(drive, 1);
 #endif
+			spin_unlock_irqrestore(ch->lock, flags);
 		}
 
 		/* Only CD-ROMs and tape drives support DSC overlap.  But only
@@ -1078,13 +1103,8 @@
  *
  * FIXME: Check whatever we maybe don't call it twice!.
  */
-int ide_unregister_subdriver(struct ata_device *drive)
+int ata_unregister_device(struct ata_device *drive)
 {
-#if 0
-	if (__MOD_IN_USE(ata_ops(drive)->owner))
-		return 1;
-#endif
-
 	if (drive->usage || drive->busy || !ata_ops(drive))
 		return 1;
 
@@ -1120,7 +1140,7 @@
 EXPORT_SYMBOL(register_ata_driver);
 
 /*
- * Unregister an ATA subdriver for a particular device type.
+ * Unregister an ATA sub-driver for a particular device type.
  */
 void unregister_ata_driver(struct ata_operations *driver)
 {
@@ -1156,8 +1176,8 @@
 
 devfs_handle_t ide_devfs_handle;
 
-EXPORT_SYMBOL(ide_register_subdriver);
-EXPORT_SYMBOL(ide_unregister_subdriver);
+EXPORT_SYMBOL(ata_register_device);
+EXPORT_SYMBOL(ata_unregister_device);
 EXPORT_SYMBOL(ata_revalidate);
 EXPORT_SYMBOL(ide_register_hw);
 EXPORT_SYMBOL(ide_unregister);
@@ -1432,8 +1452,14 @@
 		while ((options = next) != NULL) {
 			if ((next = strchr(options,' ')) != NULL)
 				*next++ = 0;
-			if (!ide_setup(options))
-				printk(KERN_ERR "Unknown option '%s'\n", options);
+			if (!strncmp(options,"hd",2)) {
+				if (!ata_hd_setup(options+2))
+					printk(KERN_ERR "Unknown option '%s'\n", options);
+			}
+			else if (!strncmp(options,"ide",3)) {
+				if (!ide_setup(options+3))
+					printk(KERN_ERR "Unknown option '%s'\n", options);
+			}
 		}
 	}
 	return ata_module_init();
@@ -1457,6 +1483,7 @@
 #ifndef MODULE
 
 /* command line option parser */
-__setup("", ide_setup);
+__setup("ide", ide_setup);
+__setup("hd", ata_hd_setup);
 
 #endif
diff -Nru a/drivers/ide/opti621.c b/drivers/ide/opti621.c
--- a/drivers/ide/opti621.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/opti621.c	Thu Aug  1 14:17:36 2002
@@ -244,13 +244,15 @@
 
 }
 
-/* Main tune procedure, called from tuneproc. */
+/* Main tune procedure, called from tuneproc.
+   Assumes IRQ's are disabled or at least that no other process will
+   attempt to access the IDE registers concurrently.
+*/
 static void opti621_tune_drive(struct ata_device *drive, u8 pio)
 {
 	/* primary and secondary drives share some registers,
 	 * so we have to program both drives
 	 */
-	unsigned long flags;
 	u8 pio1, pio2;
 	pio_clocks_t first, second;
 	int ax, drdy;
@@ -281,9 +283,6 @@
 		hwif->name, ax, second.data_time, second.recovery_time, drdy);
 #endif
 
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
-
 	reg_base = hwif->io_ports[IDE_DATA_OFFSET];
 	outb(0xc0, reg_base+CNTRL_REG);	/* allow Register-B */
 	outb(0xff, reg_base+5);		/* hmm, setupvic.exe does this ;-) */
@@ -306,8 +305,6 @@
 
 	write_reg(misc, MISC_REG);	/* set address setup, DRDY timings,   */
 					/*  and read prefetch for both drives */
-
-	restore_flags(flags);	/* all CPUs */
 }
 
 /*
diff -Nru a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c
--- a/drivers/ide/pcidma.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/pcidma.c	Thu Aug  1 14:17:36 2002
@@ -379,12 +379,6 @@
 {
 	struct ata_channel *ch = drive->channel;
 	unsigned int *table = ch->dmatable_cpu;
-#ifdef CONFIG_BLK_DEV_TRM290
-	unsigned int is_trm290_chipset = (ch->chipset == ide_trm290);
-#else
-	const int is_trm290_chipset = 0;
-#endif
-	unsigned int count = 0;
 	int i;
 	struct scatterlist *sg;
 
@@ -392,68 +386,29 @@
 	if (!i)
 		return 0;
 
+	BUG_ON(i > PRD_ENTRIES);
+
 	sg = ch->sg_table;
-	while (i) {
-		u32 cur_addr;
-		u32 cur_len;
-
-		cur_addr = sg_dma_address(sg);
-		cur_len = sg_dma_len(sg);
-
-		/*
-		 * Fill in the dma table, without crossing any 64kB boundaries.
-		 * Most hardware requires 16-bit alignment of all blocks,
-		 * but the trm290 requires 32-bit alignment.
-		 */
-
-		while (cur_len) {
-			u32 xcount, bcount = 0x10000 - (cur_addr & 0xffff);
-
-			if (count++ >= PRD_ENTRIES) {
-				printk("ide-dma: count %d, sg_nents %d, cur_len %d, cur_addr %u\n",
-						count, ch->sg_nents, cur_len, cur_addr);
-				BUG();
-			}
-
-			if (bcount > cur_len)
-				bcount = cur_len;
-			*table++ = cpu_to_le32(cur_addr);
-			xcount = bcount & 0xffff;
-			if (is_trm290_chipset)
-				xcount = ((xcount >> 2) - 1) << 16;
-			if (xcount == 0x0000) {
-		        /*
-			 * Most chipsets correctly interpret a length of
-			 * 0x0000 as 64KB, but at least one (e.g. CS5530)
-			 * misinterprets it as zero (!). So here we break
-			 * the 64KB entry into two 32KB entries instead.
-			 */
-				if (count++ >= PRD_ENTRIES) {
-					pci_unmap_sg(ch->pci_dev, sg,
-						     ch->sg_nents,
-						     ch->sg_dma_direction);
-					return 0;
-				}
-
-				*table++ = cpu_to_le32(0x8000);
-				*table++ = cpu_to_le32(cur_addr + 0x8000);
-				xcount = 0x8000;
-			}
-			*table++ = cpu_to_le32(xcount);
-			cur_addr += bcount;
-			cur_len -= bcount;
-		}
+	while (i--) {
+		u32 cur_addr = sg_dma_address(sg);
+		u32 cur_len = sg_dma_len(sg) & 0xffff;
+
+		/* Delete this test after linux ~2.5.35, as we care
+		   about performance in this loop. */
+		BUG_ON(cur_len > ch->max_segment_size);
+
+		*table++ = cpu_to_le32(cur_addr);
+		*table++ = cpu_to_le32(cur_len);
 
 		sg++;
-		i--;
 	}
 
-	if (!count)
-		printk(KERN_ERR "%s: empty DMA table?\n", ch->name);
-	else if (!is_trm290_chipset)
+#ifdef CONFIG_BLK_DEV_TRM290
+	if (ch->chipset == ide_trm290)
 		*--table |= cpu_to_le32(0x80000000);
+#endif
 
-	return count;
+	return ch->sg_nents;
 }
 
 /*
diff -Nru a/drivers/ide/probe.c b/drivers/ide/probe.c
--- a/drivers/ide/probe.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/probe.c	Thu Aug  1 14:17:36 2002
@@ -41,19 +41,10 @@
 extern struct ata_device * get_info_ptr(kdev_t);
 
 /*
- * This is called from the partition-table code in pt/msdos.c.
+ * This is called from the partition-table code in pt/msdos.c
+ * to invent a translated geometry.
  *
- * It has two tasks:
- *
- * (I) to handle Ontrack DiskManager by offsetting everything by 63 sectors,
- *  or to handle EZdrive by remapping sector 0 to sector 1.
- *
- * (II) to invent a translated geometry.
- *
- * Part (I) is suppressed if the user specifies the "noremap" option
- * on the command line.
- *
- * Part (II) is suppressed if the user specifies an explicit geometry.
+ * This is suppressed if the user specifies an explicit geometry.
  *
  * The ptheads parameter is either 0 or tells about the number of
  * heads shown by the end of the first nonempty partition.
@@ -83,21 +74,6 @@
 	if (!drive)
 		return 0;
 
-	/* remap? */
-	if (drive->remap_0_to_1 != 2) {
-		if (xparm == 1) {		/* DM */
-			drive->sect0 = 63;
-			msg1 = " [remap +63]";
-			ret = 1;
-		} else if (xparm == -1) {	/* EZ-Drive */
-			if (drive->remap_0_to_1 == 0) {
-				drive->remap_0_to_1 = 1;
-				msg1 = " [remap 0->1]";
-				ret = 1;
-			}
-		}
-	}
-
 	/* There used to be code here that assigned drive->id->CHS to
 	 * drive->CHS and that to drive->bios_CHS. However, some disks have
 	 * id->C/H/S = 4092/16/63 but are larger than 2.1 GB.  In such cases
@@ -1001,22 +977,24 @@
 			ch->drive = drive;
 
 		/*
-		 * Init the per device request queue
+		 * Init the per device request queue.
 		 */
 
 		q = &drive->queue;
-		q->queuedata = drive->channel;
+		q->queuedata = drive;
 		blk_init_queue(q, do_ide_request, drive->channel->lock);
-		blk_queue_segment_boundary(q, 0xffff);
+		blk_queue_segment_boundary(q, ch->seg_boundary_mask);
+		blk_queue_max_segment_size(q, ch->max_segment_size);
 
-		/* ATA can do up to 128K per request, pdc4030 needs smaller limit */
+		/* ATA can do up to 128K per request, pdc4030 needs smaller
+		 * limit. */
 #ifdef CONFIG_BLK_DEV_PDC4030
 		if (drive->channel->chipset == ide_pdc4030)
 			max_sectors = 127;
 #endif
 		blk_queue_max_sectors(q, max_sectors);
 
-		/* IDE DMA can do PRD_ENTRIES number of segments. */
+		/* ATA DMA can do PRD_ENTRIES number of segments. */
 		blk_queue_max_hw_segments(q, PRD_ENTRIES);
 
 		/* FIXME: This is a driver limit and could be eliminated. */
@@ -1065,6 +1043,9 @@
 static void channel_init(struct ata_channel *ch)
 {
 	struct gendisk *gd;
+	struct hd_struct *part;
+	devfs_handle_t *de_arr;
+	char *flags;
 	unsigned int unit;
 	extern devfs_handle_t ide_devfs_handle;
 
@@ -1082,14 +1063,19 @@
 		}
 	}
 #ifdef CONFIG_BLK_DEV_HD
-	if (ch->irq == HD_IRQ && ch->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
+
+	/* The first "legacy"  HD gets distinguished by the IRQ it is attached
+	 * to and the IO port it takes.
+	 */
+
+	if (ch->irq == 14 && ch->io_ports[IDE_DATA_OFFSET] != 0x1f0) {
 		printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", ch->name);
 
 		return;
 	}
 #endif
 
-	if (devfs_register_blkdev(ch->major, ch->name, ide_fops)) {
+	if (register_blkdev(ch->major, ch->name, ide_fops)) {
 		printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", ch->name, ch->major);
 
 		return;
@@ -1120,43 +1106,42 @@
 	/* Initialize partition and global device data.
 	 */
 
-	gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
+	gd = kmalloc (MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL);
 	if (!gd)
 		goto err_kmalloc_gd;
 
-	memset(gd, 0, sizeof(struct gendisk));
-	gd->sizes = kmalloc(ATA_MINORS * sizeof(int), GFP_KERNEL);
-	if (!gd->sizes)
-		goto err_kmalloc_gd_sizes;
-	memset(gd->sizes, 0, ATA_MINORS*sizeof(gd->sizes[0]));
+	memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk));
 
-	gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
-	if (!gd->part)
+	part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
+	if (!part)
 		goto err_kmalloc_gd_part;
-	memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct));
+	memset(part, 0, ATA_MINORS * sizeof(struct hd_struct));
 
-	gd->de_arr = kmalloc (sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
-	if (!gd->de_arr)
+	de_arr = kmalloc (sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL);
+	if (!de_arr)
 		goto err_kmalloc_gd_de_arr;
-	memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
+	memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES);
 
-	gd->flags = kmalloc (sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
-	if (!gd->flags)
+	flags = kmalloc (sizeof(char) * MAX_DRIVES, GFP_KERNEL);
+	if (!flags)
 		goto err_kmalloc_gd_flags;
-	memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
-
-	for (unit = 0; unit < MAX_DRIVES; ++unit)
-		ch->drives[unit].part = &gd->part[unit << PARTN_BITS];
+	memset(flags, 0, sizeof(char) * MAX_DRIVES);
 
-	gd->major	= ch->major;		/* our major device number */
-	gd->major_name	= IDE_MAJOR_NAME;	/* treated special in genhd.c */
-	gd->minor_shift	= PARTN_BITS;		/* num bits for partitions */
-	gd->nr_real	= MAX_DRIVES;		/* current num real drives */
-	gd->next	= NULL;			/* linked list of major devs */
-	gd->fops        = ide_fops;             /* file operations */
-
-	ch->gd = gd;
-	add_gendisk(gd);
+	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+		gd[unit].part = part + (unit << PARTN_BITS);
+		gd[unit].de_arr = de_arr + unit;
+		gd[unit].flags = flags + unit;
+		ch->drives[unit].part = gd[unit].part;
+		gd[unit].major	= ch->major;
+		gd[unit].first_minor = unit << PARTN_BITS;
+		/* treated special in genhd.c */
+		gd[unit].major_name = IDE_MAJOR_NAME;
+		gd[unit].minor_shift = PARTN_BITS;
+		gd[unit].nr_real = 1;
+		gd[unit].fops = ide_fops;
+		ch->gd[unit] = gd + unit;
+		add_gendisk(gd + unit);
+	}
 
 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
 		char name[80];
@@ -1177,12 +1162,10 @@
 	return;
 
 err_kmalloc_gd_flags:
-	kfree(gd->de_arr);
+	kfree(de_arr);
 err_kmalloc_gd_de_arr:
-	kfree(gd->part);
+	kfree(part);
 err_kmalloc_gd_part:
-	kfree(gd->sizes);
-err_kmalloc_gd_sizes:
 	kfree(gd);
 err_kmalloc_gd:
 	printk(KERN_CRIT "(%s) Out of memory\n", __FUNCTION__);
diff -Nru a/drivers/ide/qd65xx.c b/drivers/ide/qd65xx.c
--- a/drivers/ide/qd65xx.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/ide/qd65xx.c	Thu Aug  1 14:17:39 2002
@@ -1,8 +1,6 @@
 /*
  *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
- */
-
-/*
+ *
  *  Version 0.03	Cleaned auto-tune, added probe
  *  Version 0.04	Added second channel tuning
  *  Version 0.05	Enhanced tuning ; added qd6500 support
@@ -81,36 +79,12 @@
  * bit 5 : status, but of what ?
  * bit 6 : always set 1 by dos driver
  * bit 7 : set 1 for non-ATAPI devices on primary port
- * 	(maybe read-ahead and post-write buffer ?)
+ *	(maybe read-ahead and post-write buffer ?)
  */
 
 static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
 
-static void qd_write_reg(u8 content, unsigned int reg)
-{
-	unsigned long flags;
-
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
-	outb(content,reg);
-	restore_flags(flags);	/* all CPUs */
-}
-
-static u8 __init qd_read_reg(unsigned int reg)
-{
-	unsigned long flags;
-	u8 read;
-
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
-	read = inb(reg);
-	restore_flags(flags);	/* all CPUs */
-	return read;
-}
-
 /*
- * qd_select:
- *
  * This routine is invoked from ide.c to prepare for access to a given drive.
  */
 
@@ -120,12 +94,10 @@
 		(QD_TIMREG(drive) & 0x02);
 
 	if (timings[index] != QD_TIMING(drive))
-		qd_write_reg(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
+		outb(timings[index] = QD_TIMING(drive), QD_TIMREG(drive));
 }
 
 /*
- * qd6500_compute_timing
- *
  * computes the timing value where
  *	lower nibble represents active time,   in count of VLB clocks
  *	upper nibble represents recovery time, in count of VLB clocks
@@ -147,8 +119,6 @@
 }
 
 /*
- * qd6580_compute_timing
- *
  * idem for qd6580
  */
 
@@ -161,8 +131,6 @@
 }
 
 /*
- * qd_find_disk_type
- *
  * tries to find timing from dos driver's table
  */
 
@@ -187,8 +155,6 @@
 }
 
 /*
- * qd_timing_ok:
- *
  * check whether timings don't conflict
  */
 
@@ -201,8 +167,6 @@
 }
 
 /*
- * qd_set_timing:
- *
  * records the timing, and enables selectproc as needed
  */
 
@@ -221,10 +185,6 @@
 	printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
 }
 
-/*
- * qd6500_tune_drive
- */
-
 static void qd6500_tune_drive(struct ata_device *drive, u8 pio)
 {
 	int active_time   = 175;
@@ -242,10 +202,6 @@
 	qd_set_timing(drive, qd6500_compute_timing(drive->channel, active_time, recovery_time));
 }
 
-/*
- * qd6580_tune_drive
- */
-
 static void qd6580_tune_drive(struct ata_device *drive, u8 pio)
 {
 	struct ata_timing *t;
@@ -291,7 +247,7 @@
 	}
 
 	if (!drive->channel->unit && drive->type != ATA_DISK) {
-		qd_write_reg(0x5f, QD_CONTROL_PORT);
+		outb(0x5f, QD_CONTROL_PORT);
 		printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n", drive->name, drive->channel->name);
 	}
 
@@ -299,8 +255,6 @@
 }
 
 /*
- * qd_testreg
- *
  * tests if the given port is a register
  */
 
@@ -308,15 +262,11 @@
 {
 	u8 savereg;
 	u8 readreg;
-	unsigned long flags;
 
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
 	savereg = inb_p(port);
 	outb_p(QD_TESTVAL, port);	/* safe value */
 	readreg = inb_p(port);
 	outb(savereg, port);
-	restore_flags(flags);	/* all CPUs */
 
 	if (savereg == QD_TESTVAL) {
 		printk(KERN_ERR "Outch ! the probe for qd65xx isn't reliable !\n");
@@ -329,8 +279,6 @@
 }
 
 /*
- * qd_setup:
- *
  * called to setup an ata channel : adjusts attributes & links for tuning
  */
 
@@ -349,8 +297,6 @@
 }
 
 /*
- * qd_unsetup:
- *
  * called to unsetup an ata channel : back to default values, unlinks tuning
  */
 void __init qd_unsetup(int unit) {
@@ -368,13 +314,13 @@
 
 	if (tuneproc == (void *) qd6500_tune_drive) {
 		// will do it for both
-		qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+		outb(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
 	} else if (tuneproc == (void *) qd6580_tune_drive) {
 		if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
-			qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
-			qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
+			outb(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+			outb(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
 		} else {
-			qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
+			outb(unit ? QD6580_DEF_DATA2 : QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
 		}
 	} else {
 		printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
@@ -383,8 +329,6 @@
 }
 
 /*
- * qd_probe:
- *
  * looks at the specified baseport, and if qd found, registers & initialises it
  * return 1 if another qd may be probed
  */
@@ -394,7 +338,7 @@
 	u8 config;
 	int unit;
 
-	config = qd_read_reg(QD_CONFIG_PORT);
+	config = inb(QD_CONFIG_PORT);
 
 	if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1;
 
@@ -425,7 +369,7 @@
 
 		/* qd6580 found */
 
-		control = qd_read_reg(QD_CONTROL_PORT);
+		control = inb(QD_CONTROL_PORT);
 
 		printk(KERN_NOTICE "qd6580 at %#x\n", base);
 		printk(KERN_DEBUG "qd6580: config=%#x, control=%#x, ID3=%u\n", config, control, QD_ID3);
@@ -434,7 +378,7 @@
 			/* secondary disabled */
 			printk(KERN_INFO "%s: qd6580: single IDE board\n", ide_hwifs[unit].name);
 			qd_setup(unit, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA2, &qd6580_tune_drive);
-			qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT);
+			outb(QD_DEF_CONTR, QD_CONTROL_PORT);
 
 			return 1;
 		} else {
@@ -443,7 +387,7 @@
 
 			qd_setup(ATA_PRIMARY, base, config | (control << 8), QD6580_DEF_DATA, QD6580_DEF_DATA, &qd6580_tune_drive);
 			qd_setup(ATA_SECONDARY, base, config | (control << 8), QD6580_DEF_DATA2, QD6580_DEF_DATA2, &qd6580_tune_drive);
-			qd_write_reg(QD_DEF_CONTR, QD_CONTROL_PORT);
+			outb(QD_DEF_CONTR, QD_CONTROL_PORT);
 
 			return 0; /* no other qd65xx possible */
 		}
@@ -454,8 +398,6 @@
 
 #ifndef MODULE
 /*
- * init_qd65xx:
- *
  * called by ide.c when parsing command line
  */
 
diff -Nru a/drivers/ide/trm290.c b/drivers/ide/trm290.c
--- a/drivers/ide/trm290.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/ide/trm290.c	Thu Aug  1 14:17:36 2002
@@ -255,6 +255,7 @@
 	struct pci_dev *dev = hwif->pci_dev;
 
 	hwif->chipset = ide_trm290;
+	hwif->seg_boundary_mask = 0xffffffff;
 	cfgbase = pci_resource_start(dev, 4);
 	if ((dev->class & 5) && cfgbase)
 	{
diff -Nru a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c
--- a/drivers/ide/umc8672.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/ide/umc8672.c	Thu Aug  1 14:17:40 2002
@@ -108,19 +108,14 @@
 
 static void tune_umc(struct ata_device *drive, u8 pio)
 {
-	unsigned long flags;
-
 	if (pio == 255)
 		pio = ata_timing_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
 	else
 		pio = min_t(u8, pio, 4);
 
 	printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]);
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
 	current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
 	umc_set_speeds (current_speeds);
-	restore_flags(flags);	/* all CPUs */
 }
 
 void __init init_umc8672(void)	/* called from ide.c */
diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/input/evdev.c	Thu Aug  1 14:17:41 2002
@@ -233,6 +233,7 @@
 	struct evdev_list *list = file->private_data;
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
+	struct input_absinfo abs;
 	int t, u;
 
 	if (!evdev->exist) return -ENODEV;
@@ -378,11 +379,14 @@
 
 				int t = _IOC_NR(cmd) & ABS_MAX;
 
-				if (put_user(dev->abs[t],     ((int *) arg) + 0)) return -EFAULT;
-				if (put_user(dev->absmin[t],  ((int *) arg) + 1)) return -EFAULT;
-				if (put_user(dev->absmax[t],  ((int *) arg) + 2)) return -EFAULT;
-				if (put_user(dev->absfuzz[t], ((int *) arg) + 3)) return -EFAULT;
-				if (put_user(dev->absflat[t], ((int *) arg) + 4)) return -EFAULT;
+				abs.value = dev->abs[t];
+				abs.minimum = dev->absmin[t];
+				abs.maximum = dev->absmax[t];
+				abs.fuzz = dev->absfuzz[t];
+				abs.flat = dev->absflat[t];
+
+				if (copy_to_user((void *) arg, &abs, sizeof(struct input_absinfo)))
+					return -EFAULT;
 
 				return 0;
 			}
@@ -391,11 +395,14 @@
 
 				int t = _IOC_NR(cmd) & ABS_MAX;
 
-				if (get_user(dev->abs[t],     ((int *) arg) + 0)) return -EFAULT;
-				if (get_user(dev->absmin[t],  ((int *) arg) + 1)) return -EFAULT;
-				if (get_user(dev->absmax[t],  ((int *) arg) + 2)) return -EFAULT;
-				if (get_user(dev->absfuzz[t], ((int *) arg) + 3)) return -EFAULT;
-				if (get_user(dev->absflat[t], ((int *) arg) + 4)) return -EFAULT;
+				if (copy_from_user(&abs, (void *) arg, sizeof(struct input_absinfo)))
+					return -EFAULT;
+
+				dev->abs[t] = abs.value;
+				dev->absmin[t] = abs.minimum;
+				dev->absmax[t] = abs.maximum;
+				dev->absfuzz[t] = abs.fuzz;
+				dev->absflat[t] = abs.flat;
 
 				return 0;
 			}
diff -Nru a/drivers/input/input.c b/drivers/input/input.c
--- a/drivers/input/input.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/input/input.c	Thu Aug  1 14:17:40 2002
@@ -100,18 +100,14 @@
 			if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value)
 				return;
 
-			if (value == 2) break;
+			if (value == 2)
+				break;
 
 			change_bit(code, dev->key);
 
-			if (test_bit(EV_REP, dev->evbit) && dev->timer.function) {
-				if (value) {
-					mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]);
-					dev->repeat_key = code;
-					break;
-				}
-				if (dev->repeat_key == code)
-					del_timer(&dev->timer);
+			if (test_bit(EV_REP, dev->evbit) && value) {
+				dev->repeat_key = code;
+				mod_timer(&dev->timer, jiffies + dev->rep[REP_DELAY]);
 			}
 
 			break;
@@ -204,8 +200,13 @@
 static void input_repeat_key(unsigned long data)
 {
 	struct input_dev *dev = (void *) data;
+
+	if (!test_bit(dev->repeat_key, dev->key))
+		return;
+
 	input_event(dev, EV_KEY, dev->repeat_key, 2);
 	input_sync(dev);
+
 	mod_timer(&dev->timer, jiffies + dev->rep[REP_PERIOD]);
 }
 
@@ -268,6 +269,7 @@
  *
  *     Returns nothing.
  */
+
 #define input_find_and_remove(type, initval, targ, next)		\
 	do {								\
 		type **ptr;						\
@@ -513,7 +515,7 @@
  * Kill any pending repeat timers.
  */
 
-	del_timer(&dev->timer);
+	del_timer_sync(&dev->timer);
 
 /*
  * Notify handlers.
@@ -820,7 +822,7 @@
 	entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL);
 	entry->owner = THIS_MODULE;
 #endif
-	if (devfs_register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
+	if (register_chrdev(INPUT_MAJOR, "input", &input_fops)) {
 		printk(KERN_ERR "input: unable to register char major %d", INPUT_MAJOR);
 		return -EBUSY;
 	}
@@ -838,7 +840,7 @@
 	remove_proc_entry("input", proc_bus);
 #endif
 	devfs_unregister(input_devfs_handle);
-        if (devfs_unregister_chrdev(INPUT_MAJOR, "input"))
+        if (unregister_chrdev(INPUT_MAJOR, "input"))
                 printk(KERN_ERR "input: can't unregister char major %d", INPUT_MAJOR);
 }
 
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
--- a/drivers/input/serio/serio.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/input/serio/serio.c	Thu Aug  1 14:17:36 2002
@@ -95,9 +95,9 @@
 
 	do {
 		serio_handle_events();
+		interruptible_sleep_on(&serio_wait); 
 		if (current->flags & PF_FREEZE)
 			refrigerator(PF_IOTHREAD);
-		interruptible_sleep_on(&serio_wait); 
 	} while (!signal_pending(current));
 
 	printk(KERN_DEBUG "serio: kseriod exiting");
diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
--- a/drivers/isdn/capi/capi.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/isdn/capi/capi.c	Thu Aug  1 14:17:41 2002
@@ -1485,7 +1485,7 @@
 	} else
 		strcpy(rev, "1.0");
 
-	if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) {
+	if (register_chrdev(capi_major, "capi20", &capi_fops)) {
 		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
 		MOD_DEC_USE_COUNT;
 		return -EIO;
@@ -1498,7 +1498,7 @@
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	if (capinc_tty_init() < 0) {
-		devfs_unregister_chrdev(capi_major, "capi20");
+		unregister_chrdev(capi_major, "capi20");
 		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
@@ -1526,8 +1526,8 @@
 {
 	proc_exit();
 
-	devfs_unregister_chrdev(capi_major, "capi20");
-	devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0));
+	unregister_chrdev(capi_major, "capi20");
+	devfs_find_and_unregister(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0);
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	capinc_tty_exit();
diff -Nru a/drivers/isdn/hisax/Config.in b/drivers/isdn/hisax/Config.in
--- a/drivers/isdn/hisax/Config.in	Thu Aug  1 14:17:36 2002
+++ b/drivers/isdn/hisax/Config.in	Thu Aug  1 14:17:36 2002
@@ -43,9 +43,9 @@
    bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
 #      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
-      bool '  Formula-n enter:now PCI card' CONFIG_HISAX_ENTERNOW_PCI
+      bool '  Formula-n enter:now PCI card (EXPERIMENTAL)' CONFIG_HISAX_ENTERNOW_PCI
       if [ "$CONFIG_SPARC32" = "y" -o "$CONFIG_SPARC64" = "y" ]; then
-	 bool '  Am7930' CONFIG_HISAX_AMD7930
+	 bool '  Am7930 (EXPERIMENTAL)' CONFIG_HISAX_AMD7930
       fi
    fi
    bool '  HiSax debugging' CONFIG_HISAX_DEBUG
diff -Nru a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c
--- a/drivers/isdn/hysdn/boardergo.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/isdn/hysdn/boardergo.c	Thu Aug  1 14:17:40 2002
@@ -424,16 +424,19 @@
 int
 ergo_inithardware(hysdn_card * card)
 {
-	if (check_region(card->iobase + PCI9050_INTR_REG, 1) ||
-	    check_region(card->iobase + PCI9050_USER_IO, 1))
+	if (!request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN")) 
+		return (-1);
+	if (!request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN")) {
+		release_region(card->iobase + PCI9050_INTR_REG, 1);
 		return (-1);	/* ports already in use */
-
+	}
 	card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1;
-	if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE)))
+	if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) {
+		release_region(card->iobase + PCI9050_INTR_REG, 1);
+		release_region(card->iobase + PCI9050_USER_IO, 1);
 		return (-1);
+	}
 
-	request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN");
-	request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN");
 	ergo_stopcard(card);	/* disable interrupts */
 	if (request_irq(card->irq, ergo_interrupt, SA_SHIRQ, "HYSDN", card)) {
 		ergo_releasehardware(card); /* return the acquired hardware */
diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
--- a/drivers/isdn/i4l/isdn_common.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/isdn/i4l/isdn_common.c	Thu Aug  1 14:17:40 2002
@@ -2266,7 +2266,7 @@
 		init_waitqueue_head(&dev->mdm.info[i].open_wait);
 		init_waitqueue_head(&dev->mdm.info[i].close_wait);
 	}
-	if (devfs_register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
+	if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
 		printk(KERN_WARNING "isdn: Could not register control devices\n");
 		vfree(dev);
 		return -EIO;
@@ -2280,7 +2280,7 @@
 			tty_unregister_driver(&dev->mdm.tty_modem);
 		vfree(dev);
 		isdn_cleanup_devfs();
-		devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
+		unregister_chrdev(ISDN_MAJOR, "isdn");
 		return -EIO;
 	}
 #ifdef CONFIG_ISDN_PPP
@@ -2291,7 +2291,7 @@
 		for (i = 0; i < ISDN_MAX_CHANNELS; i++)
 			kfree(dev->mdm.info[i].xmit_buf - 4);
 		isdn_cleanup_devfs();
-		devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
+		unregister_chrdev(ISDN_MAJOR, "isdn");
 		vfree(dev);
 		return -EIO;
 	}
@@ -2354,7 +2354,7 @@
 		kfree(dev->mdm.info[i].fax);
 #endif
 	}
-	if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
+	if (unregister_chrdev(ISDN_MAJOR, "isdn") != 0) {
 		printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
 		restore_flags(flags);
 	} else {
diff -Nru a/drivers/macintosh/Makefile b/drivers/macintosh/Makefile
--- a/drivers/macintosh/Makefile	Thu Aug  1 14:17:40 2002
+++ b/drivers/macintosh/Makefile	Thu Aug  1 14:17:40 2002
@@ -4,7 +4,7 @@
 
 # Objects that export symbols.
 
-export-objs	:= adb.o rtc.o mac_hid.o via-pmu.o
+export-objs	:= adb.o mac_hid.o via-pmu.o
 
 # Object file lists.
 
diff -Nru a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
--- a/drivers/macintosh/adb.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/macintosh/adb.c	Thu Aug  1 14:17:40 2002
@@ -815,7 +815,7 @@
 static void
 adbdev_init(void)
 {
-	if (devfs_register_chrdev(ADB_MAJOR, "adb", &adb_fops))
+	if (register_chrdev(ADB_MAJOR, "adb", &adb_fops))
 		printk(KERN_ERR "adb: unable to get major %d\n", ADB_MAJOR);
 	else
 		devfs_register (NULL, "adb", DEVFS_FL_DEFAULT,
diff -Nru a/drivers/md/lvm.c b/drivers/md/lvm.c
--- a/drivers/md/lvm.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/md/lvm.c	Thu Aug  1 14:17:40 2002
@@ -213,7 +213,6 @@
 #include <linux/proc_fs.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
 #include <asm/ioctl.h>
 #include <asm/uaccess.h>
@@ -388,19 +387,18 @@
  */
 int lvm_init(void)
 {
-	if (devfs_register_chrdev(LVM_CHAR_MAJOR,
+	if (register_chrdev(LVM_CHAR_MAJOR,
 				  lvm_name, &lvm_chr_fops) < 0) {
-		printk(KERN_ERR "%s -- devfs_register_chrdev failed\n",
+		printk(KERN_ERR "%s -- register_chrdev failed\n",
 		       lvm_name);
 		return -EIO;
 	}
 
-	if (devfs_register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0)
-	{
-		printk("%s -- devfs_register_blkdev failed\n", lvm_name);
-		if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
+	if (register_blkdev(MAJOR_NR, lvm_name, &lvm_blk_dops) < 0) {
+		printk("%s -- register_blkdev failed\n", lvm_name);
+		if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
 			printk(KERN_ERR
-			       "%s -- devfs_unregister_chrdev failed\n",
+			       "%s -- unregister_chrdev failed\n",
 			       lvm_name);
 		return -EIO;
 	}
@@ -442,11 +440,11 @@
  */
 static void lvm_cleanup(void)
 {
-	if (devfs_unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
-		printk(KERN_ERR "%s -- devfs_unregister_chrdev failed\n",
+	if (unregister_chrdev(LVM_CHAR_MAJOR, lvm_name) < 0)
+		printk(KERN_ERR "%s -- unregister_chrdev failed\n",
 		       lvm_name);
-	if (devfs_unregister_blkdev(MAJOR_NR, lvm_name) < 0)
-		printk(KERN_ERR "%s -- devfs_unregister_blkdev failed\n",
+	if (unregister_blkdev(MAJOR_NR, lvm_name) < 0)
+		printk(KERN_ERR "%s -- unregister_blkdev failed\n",
 		       lvm_name);
 
 	del_gendisk(&lvm_gendisk);
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/md/md.c	Thu Aug  1 14:17:39 2002
@@ -122,7 +122,6 @@
 	.major_name	= "md",
 	.minor_shift	= 0,
 	.part		= md_hd_struct,
-	.sizes		= md_size,
 	.nr_real	= MAX_MD_DEVS,
 	.next		= NULL,
 	.fops		= &md_fops,
@@ -3177,7 +3176,6 @@
 	for(i = 0; i < MAX_MD_DEVS; i++) {
 		md_size[i] = 0;
 	}
-	blk_size[MAJOR_NR] = md_size;
 
 	dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
@@ -3207,8 +3205,7 @@
 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
 			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
 
-	if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops))
-	{
+	if (register_blkdev (MAJOR_NR, "md", &md_fops)) {
 		printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR);
 		return (-1);
 	}
@@ -3412,12 +3409,13 @@
 				*p++ = 0;
 
 			dev = name_to_kdev_t(devname);
-			handle = devfs_find_handle(NULL, devname, major(dev), minor(dev),
-							DEVFS_SPECIAL_BLK, 1);
+			handle = devfs_get_handle(NULL, devname, major(dev), minor(dev),
+						  DEVFS_SPECIAL_BLK, 1);
 			if (handle != 0) {
 				unsigned major, minor;
 				devfs_get_maj_min(handle, &major, &minor);
 				dev = mk_kdev(major, minor);
+				devfs_put(handle);
 			}
 			if (kdev_none(dev)) {
 				printk(KERN_WARNING "md: Unknown device name: %s\n", devname);
@@ -3567,7 +3565,7 @@
 	md_unregister_thread(md_recovery_thread);
 	devfs_unregister(devfs_handle);
 
-	devfs_unregister_blkdev(MAJOR_NR,"md");
+	unregister_blkdev(MAJOR_NR,"md");
 	unregister_reboot_notifier(&md_notifier);
 	unregister_sysctl_table(raid_table_header);
 #ifdef CONFIG_PROC_FS
diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
--- a/drivers/media/video/videodev.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/media/video/videodev.c	Thu Aug  1 14:17:36 2002
@@ -484,8 +484,7 @@
 static int __init videodev_init(void)
 {
 	printk(KERN_INFO "Linux video capture interface: v1.00\n");
-	if(devfs_register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops))
-	{
+	if (register_chrdev(VIDEO_MAJOR,"video_capture", &video_fops)) {
 		printk("video_dev: unable to get major %d\n", VIDEO_MAJOR);
 		return -EIO;
 	}
@@ -502,7 +501,7 @@
 #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
 	videodev_proc_destroy ();
 #endif
-	devfs_unregister_chrdev(VIDEO_MAJOR, "video_capture");
+	unregister_chrdev(VIDEO_MAJOR, "video_capture");
 }
 
 module_init(videodev_init)
diff -Nru a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
--- a/drivers/message/fusion/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/message/fusion/Makefile	Thu Aug  1 14:17:41 2002
@@ -43,7 +43,7 @@
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
-export-objs	:= mptbase.o mptscsih.o mptlan.o mptctl.o isense.o
+export-objs	:= mptbase.o
 
 obj-$(CONFIG_FUSION)		+= mptbase.o mptscsih.o
 obj-$(CONFIG_FUSION_ISENSE)	+= isense.o
diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
--- a/drivers/message/i2o/i2o_block.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/message/i2o/i2o_block.c	Thu Aug  1 14:17:41 2002
@@ -124,7 +124,6 @@
  *	Some of these can be made smaller later
  */
 
-static int i2ob_sizes[MAX_I2OB<<4];
 static int i2ob_media_change_flag[MAX_I2OB];
 
 static int i2ob_context;
@@ -731,7 +730,6 @@
 			{
 				for(i = unit; i <= unit+15; i++)
 				{
-					i2ob_sizes[i] = 0;
 					blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
 					i2ob[i].nr_sects = 0;
 					i2ob_gendisk.part[i].nr_sects = 0;
@@ -767,7 +765,6 @@
 					i2ob_query_device(&i2ob_dev[unit], 0x0000, 4, &size, 8);
 
 				spin_lock_irqsave(&I2O_LOCK(unit), flags);	
-				i2ob_sizes[unit] = (int)(size>>10);
 				i2ob_gendisk.part[unit].nr_sects = size>>9;
 				i2ob[unit].nr_sects = (int)(size>>9);
 				spin_unlock_irqrestore(&I2O_LOCK(unit), flags);	
@@ -1081,7 +1078,7 @@
 		{
 			struct hd_geometry g;
 			int u = minor(inode->i_rdev) & 0xF0;
-			i2o_block_biosparam(i2ob_sizes[u]<<1, 
+			i2o_block_biosparam(i2ob[u].nr_sects, 
 				&g.cylinders, &g.heads, &g.sectors);
 			g.start = get_start_sect(inode->i_bdev);
 			return copy_to_user((void *)arg, &g, sizeof(g))
@@ -1268,7 +1265,6 @@
 	
 	i2ob_query_device(dev, 0x0000, 5, &flags, 4);
 	i2ob_query_device(dev, 0x0000, 6, &status, 4);
-	i2ob_sizes[unit] = (int)(size>>10);
 	i2ob_gendisk.part[unit].nr_sects = size>>9;
 	i2ob[unit].nr_sects = (int)(size>>9);
 
@@ -1655,7 +1651,6 @@
 	for(i = unit; i <= unit+15; i++)
 	{
 		i2ob_dev[i].i2odev = NULL;
-		i2ob_sizes[i] = 0;
 		blk_queue_max_sectors(i2ob_dev[i].req_queue, 0);
 		i2ob[i].nr_sects = 0;
 		i2ob_gendisk.part[i].nr_sects = 0;
@@ -1762,7 +1757,6 @@
 	major_name:	"i2o/hd",
 	minor_shift:	4,
 	part:		i2ob,
-	sizes:		i2ob_sizes,
 	nr_real:	MAX_I2OB,
 	fops:		&i2ob_fops,
 };
diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
--- a/drivers/mtd/ftl.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/mtd/ftl.c	Thu Aug  1 14:17:39 2002
@@ -175,14 +175,12 @@
 #define XFER_FAILED	0x04
 
 static struct hd_struct ftl_hd[MINOR_NR(MAX_DEV, 0, 0)];
-static int ftl_sizes[MINOR_NR(MAX_DEV, 0, 0)];
 
 static struct gendisk ftl_gendisk = {
     major:		FTL_MAJOR,
     major_name:		"ftl",
     minor_shift:	PART_BITS,
     part:		ftl_hd,
-    sizes:		ftl_sizes,
 };
 
 /*====================================================================*/
diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
--- a/drivers/mtd/mtdblock.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/mtd/mtdblock.c	Thu Aug  1 14:17:40 2002
@@ -593,22 +593,14 @@
 	int i;
 
 	spin_lock_init(&mtdblks_lock);
-#ifdef CONFIG_DEVFS_FS
-	if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops))
-	{
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-			MTD_BLOCK_MAJOR);
-		return -EAGAIN;
-	}
-
-	devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
-	register_mtd_user(&notifier);
-#else
 	if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
 		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
 		       MTD_BLOCK_MAJOR);
 		return -EAGAIN;
 	}
+#ifdef CONFIG_DEVFS_FS
+	devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL);
+	register_mtd_user(&notifier);
 #endif
 	
 	/* We fill it in at open() time. */
@@ -630,10 +622,8 @@
 #ifdef CONFIG_DEVFS_FS
 	unregister_mtd_user(&notifier);
 	devfs_unregister(devfs_dir_handle);
-	devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME);
-#else
-	unregister_blkdev(MAJOR_NR,DEVICE_NAME);
 #endif
+	unregister_blkdev(MAJOR_NR,DEVICE_NAME);
 	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
 	blk_size[MAJOR_NR] = NULL;
 }
diff -Nru a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
--- a/drivers/mtd/mtdchar.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/mtd/mtdchar.c	Thu Aug  1 14:17:41 2002
@@ -494,26 +494,17 @@
 
 static int __init init_mtdchar(void)
 {
-#ifdef CONFIG_DEVFS_FS
-	if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
-	{
+	if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) {
 		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
 		       MTD_CHAR_MAJOR);
 		return -EAGAIN;
 	}
 
+#ifdef CONFIG_DEVFS_FS
 	devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL);
 
 	register_mtd_user(&notifier);
-#else
-	if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
-	{
-		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
-		       MTD_CHAR_MAJOR);
-		return -EAGAIN;
-	}
 #endif
-
 	return 0;
 }
 
@@ -522,10 +513,8 @@
 #ifdef CONFIG_DEVFS_FS
 	unregister_mtd_user(&notifier);
 	devfs_unregister(devfs_dir_handle);
-	devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
-#else
-	unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
 #endif
+	unregister_chrdev(MTD_CHAR_MAJOR, "mtd");
 }
 
 module_init(init_mtdchar);
diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
--- a/drivers/mtd/nftlcore.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/mtd/nftlcore.c	Thu Aug  1 14:17:36 2002
@@ -24,6 +24,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/blkpg.h>
+#include <linux/buffer_head.h>
 
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
@@ -52,17 +53,16 @@
  *  encountered, except ...
  */
 
-static int nftl_sizes[256];
-
 /* .. for the Linux partition table handling. */
+/* So why didn't you fucking go and clean it up? -- AV */
 struct hd_struct part_table[256];
 
+static struct block_device_operations nftl_fops;
 static struct gendisk nftl_gendisk = {
 	major:		MAJOR_NR,
 	major_name:	"nftl",
 	minor_shift:	NFTL_PARTN_BITS,	/* # of partition bits */
 	part:		part_table,		/* hd struct */
-	sizes:		nftl_sizes,		/* block sizes */
 };
 
 struct NFTLrecord *NFTLs[MAX_NFTLS];
@@ -143,7 +143,6 @@
 	}
 	NFTLs[firstfree] = nftl;
 	/* Finally, set up the block device sizes */
-	nftl_sizes[firstfree * 16] = nftl->nr_sects;
 	part_table[firstfree * 16].nr_sects = nftl->nr_sects;
 
 	nftl_gendisk.nr_real++;
diff -Nru a/drivers/net/8139cp.c b/drivers/net/8139cp.c
--- a/drivers/net/8139cp.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/net/8139cp.c	Thu Aug  1 14:17:40 2002
@@ -18,7 +18,7 @@
 
 	See the file COPYING in this distribution for more information.
 
-	Contribuitors:
+	Contributors:
 	
 		Wake-on-LAN support - Felipe Damasio <felipewd@terra.com.br>
 			
diff -Nru a/drivers/net/Config.in b/drivers/net/Config.in
--- a/drivers/net/Config.in	Thu Aug  1 14:17:36 2002
+++ b/drivers/net/Config.in	Thu Aug  1 14:17:36 2002
@@ -273,7 +273,7 @@
       dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
    fi
    if [ ! "$CONFIG_ATM" = "n" ]; then
-      dep_tristate '  PPP over ATM (EXPERIMENTAL)' CONFIG_PPPOATM $CONFIG_PPP
+      dep_tristate '  PPP over ATM' CONFIG_PPPOATM $CONFIG_PPP
    fi
 fi
 
diff -Nru a/drivers/net/Makefile.lib b/drivers/net/Makefile.lib
--- a/drivers/net/Makefile.lib	Thu Aug  1 14:17:41 2002
+++ b/drivers/net/Makefile.lib	Thu Aug  1 14:17:41 2002
@@ -25,7 +25,7 @@
 obj-$(CONFIG_PCNET32)		+= crc32.o
 obj-$(CONFIG_SIS900)		+= crc32.o
 obj-$(CONFIG_SMC9194)		+= crc32.o
-obj-$(CONFIG_STARFIRE)		+= crc32.o
+obj-$(CONFIG_ADAPTEC_STARFIRE)	+= crc32.o
 obj-$(CONFIG_SUNBMAC)		+= crc32.o
 obj-$(CONFIG_SUNDANCE)		+= crc32.o
 obj-$(CONFIG_SUNGEM)		+= crc32.o
diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
--- a/drivers/net/au1000_eth.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/net/au1000_eth.c	Thu Aug  1 14:17:36 2002
@@ -819,9 +819,9 @@
 				MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS));
 	if (dev->priv != NULL)
 		kfree(dev->priv);
-	kfree(dev);
 	printk(KERN_ERR "%s: au1000_probe1 failed.  Returns %d\n",
 	       dev->name, retval);
+	kfree(dev);
 	return retval;
 }
 
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/net/e1000/e1000_main.c	Thu Aug  1 14:17:40 2002
@@ -1699,7 +1699,7 @@
 {
 	atomic_inc(&adapter->irq_sem);
 	E1000_WRITE_REG(&adapter->hw, IMC, ~0);
-	synchronize_irq();
+	synchronize_irq(adapter->netdev->irq);
 }
 
 /**
diff -Nru a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
--- a/drivers/net/hamradio/baycom_ser_hdx.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/net/hamradio/baycom_ser_hdx.c	Thu Aug  1 14:17:36 2002
@@ -476,19 +476,22 @@
 	if (!dev->base_addr || dev->base_addr > 0x1000-SER12_EXTENT ||
 	    dev->irq < 2 || dev->irq > 15)
 		return -ENXIO;
-	if (check_region(dev->base_addr, SER12_EXTENT))
+	if (!request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12"))
 		return -EACCES;
 	memset(&bc->modem, 0, sizeof(bc->modem));
 	bc->hdrv.par.bitrate = 1200;
-	if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown)
+	if ((u = ser12_check_uart(dev->base_addr)) == c_uart_unknown) {
+		release_region(dev->base_addr, SER12_EXTENT);       
 		return -EIO;
+	}
 	outb(0, FCR(dev->base_addr));  /* disable FIFOs */
 	outb(0x0d, MCR(dev->base_addr));
 	outb(0, IER(dev->base_addr));
 	if (request_irq(dev->irq, ser12_interrupt, SA_INTERRUPT | SA_SHIRQ,
-			"baycom_ser12", dev))
+			"baycom_ser12", dev)) {
+		release_region(dev->base_addr, SER12_EXTENT);       
 		return -EBUSY;
-	request_region(dev->base_addr, SER12_EXTENT, "baycom_ser12");
+	}
 	/*
 	 * enable transmitter empty interrupt
 	 */
diff -Nru a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in
--- a/drivers/net/irda/Config.in	Thu Aug  1 14:17:41 2002
+++ b/drivers/net/irda/Config.in	Thu Aug  1 14:17:41 2002
@@ -19,20 +19,20 @@
       dep_tristate '  EP7211 I/R support' CONFIG_EP7211_IR $CONFIG_IRDA
    fi
    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-      dep_tristate '  ACTiSYS IR-200L dongle (Experimental)' CONFIG_ACT200L_DONGLE $CONFIG_IRDA
-      dep_tristate '  Mobile Action MA600 dongle (Experimental)' CONFIG_MA600_DONGLE $CONFIG_IRDA
+      dep_tristate '  ACTiSYS IR-200L dongle (EXPERIMENTAL)' CONFIG_ACT200L_DONGLE $CONFIG_IRDA
+      dep_tristate '  Mobile Action MA600 dongle (EXPERIMENTAL)' CONFIG_MA600_DONGLE $CONFIG_IRDA
    fi
 fi
 
 comment 'FIR device drivers'
-dep_tristate 'IrDA USB dongles (Experimental)' CONFIG_USB_IRDA $CONFIG_IRDA $CONFIG_USB $CONFIG_EXPERIMENTAL
+dep_tristate 'IrDA USB dongles (EXPERIMENTAL)' CONFIG_USB_IRDA $CONFIG_IRDA $CONFIG_USB $CONFIG_EXPERIMENTAL
 dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR  $CONFIG_IRDA
 dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
 dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
 if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
-dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
-dep_tristate 'ALi M5123 FIR (Experimental)' CONFIG_ALI_FIR $CONFIG_IRDA
-dep_tristate 'VLSI 82C147 SIR/MIR/FIR (Experimental)' CONFIG_VLSI_FIR $CONFIG_IRDA
+dep_tristate 'SMC IrCC (EXPERIMENTAL)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+dep_tristate 'ALi M5123 FIR (EXPERIMENTAL)' CONFIG_ALI_FIR $CONFIG_IRDA
+dep_tristate 'VLSI 82C147 SIR/MIR/FIR (EXPERIMENTAL)' CONFIG_VLSI_FIR $CONFIG_IRDA
 fi
 if [ "$CONFIG_ARCH_SA1100" = "y" ]; then
    dep_tristate 'SA1100 Internal IR' CONFIG_SA1100_FIR $CONFIG_IRDA
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/net/ppp_generic.c	Thu Aug  1 14:17:41 2002
@@ -785,7 +785,7 @@
 	int err;
 
 	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
-	err = devfs_register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
+	err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
 	if (err)
 		printk(KERN_ERR "failed to register PPP device (%d)\n", err);
 	devfs_handle = devfs_register(NULL, "ppp", DEVFS_FL_DEFAULT,
@@ -2509,7 +2509,7 @@
 	if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
 		printk(KERN_ERR "PPP: removing module but units remain!\n");
 	cardmap_destroy(&all_ppp_units);
-	if (devfs_unregister_chrdev(PPP_MAJOR, "ppp") != 0)
+	if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
 		printk(KERN_ERR "PPP: failed to unregister PPP device\n");
 	devfs_unregister(devfs_handle);
 }
diff -Nru a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
--- a/drivers/net/wan/Makefile	Thu Aug  1 14:17:36 2002
+++ b/drivers/net/wan/Makefile	Thu Aug  1 14:17:36 2002
@@ -6,7 +6,7 @@
 #
 
 export-objs :=	z85230.o syncppp.o comx.o sdladrv.o cycx_drv.o hdlc_generic.o \
-		dlci.o pc300_drv.o
+		dlci.o
 
 wanpipe-y			:= sdlamain.o sdla_ft1.o
 wanpipe-$(CONFIG_WANPIPE_X25)	+= sdla_x25.o
diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
--- a/drivers/net/wan/cosa.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/net/wan/cosa.c	Thu Aug  1 14:17:36 2002
@@ -373,13 +373,13 @@
 	printk(KERN_INFO "cosa: SMP found. Please mail any success/failure reports to the author.\n");
 #endif
 	if (cosa_major > 0) {
-		if (devfs_register_chrdev(cosa_major, "cosa", &cosa_fops)) {
+		if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
 			printk(KERN_WARNING "cosa: unable to get major %d\n",
 				cosa_major);
 			return -EIO;
 		}
 	} else {
-		if (!(cosa_major=devfs_register_chrdev(0, "cosa", &cosa_fops))) {
+		if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
 			printk(KERN_WARNING "cosa: unable to register chardev\n");
 			return -EIO;
 		}
@@ -395,7 +395,7 @@
 			       &cosa_fops, NULL);
 	if (!nr_cards) {
 		printk(KERN_WARNING "cosa: no devices found.\n");
-		devfs_unregister_chrdev(cosa_major, "cosa");
+		unregister_chrdev(cosa_major, "cosa");
 		return -ENODEV;
 	}
 	return 0;
@@ -422,7 +422,7 @@
 		free_dma(cosa->dma);
 		release_region(cosa->datareg,is_8bit(cosa)?2:4);
 	}
-	devfs_unregister_chrdev(cosa_major, "cosa");
+	unregister_chrdev(cosa_major, "cosa");
 }
 #endif
 
diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c
--- a/drivers/net/wan/sdla_chdlc.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/net/wan/sdla_chdlc.c	Thu Aug  1 14:17:40 2002
@@ -2852,7 +2852,7 @@
 #endif
 		if(err) {
 			printk(KERN_INFO
-				"%s: Remove route %s failed, (err %d)\n",
+				"%s: Remove route %u.%u.%u.%u failed, (err %d)\n",
 					card->devname, NIPQUAD(remote_IP_addr),
 					err);
 		} else {
diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c
--- a/drivers/parport/share.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/parport/share.c	Thu Aug  1 14:17:40 2002
@@ -1002,7 +1002,6 @@
 	/* Try to claim the port.  If this fails, we need to sleep.  */
 	r = parport_claim(dev);
 	if (r == -EAGAIN) {
-		unsigned long flags;
 #ifdef PARPORT_DEBUG_SHARING
 		printk(KERN_DEBUG "%s: parport_claim() returned -EAGAIN\n", dev->name);
 #endif
diff -Nru a/drivers/pci/access.c b/drivers/pci/access.c
--- a/drivers/pci/access.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/pci/access.c	Thu Aug  1 14:17:41 2002
@@ -7,7 +7,7 @@
  * configuration space.
  */
 
-static spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
+spinlock_t pci_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  *  Wrappers for all PCI configuration access functions.  They just check
@@ -44,3 +44,4 @@
 EXPORT_SYMBOL(pci_write_config_byte);
 EXPORT_SYMBOL(pci_write_config_word);
 EXPORT_SYMBOL(pci_write_config_dword);
+EXPORT_SYMBOL(pci_lock);
diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c
--- a/drivers/pci/proc.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/pci/proc.c	Thu Aug  1 14:17:36 2002
@@ -378,11 +378,7 @@
 	return off ? 0 : sprintf(buf,"%u\n",pci_dev->irq);
 }
 
-static struct driver_file_entry pci_irq_entry = {
-	name:	"irq",
-	mode:	S_IRUGO,
-	show:	pci_show_irq,
-};
+static DEVICE_ATTR(irq,"irq",S_IRUGO,pci_show_irq,NULL);
 
 static ssize_t pci_show_resources(struct device * dev, char * buf, size_t count, loff_t off)
 {
@@ -406,11 +402,7 @@
 	return (str - buf);
 }
 
-static struct driver_file_entry pci_resource_entry = {
-	name:	"resources",
-	mode:	S_IRUGO,
-	show:	pci_show_resources,
-};
+static DEVICE_ATTR(resource,"resource",S_IRUGO,pci_show_resources,NULL);
 
 int pci_proc_attach_device(struct pci_dev *dev)
 {
@@ -432,8 +424,8 @@
 	e->data = dev;
 	e->size = PCI_CFG_SPACE_SIZE;
 
-	device_create_file(&dev->dev,&pci_irq_entry);
-	device_create_file(&dev->dev,&pci_resource_entry);
+	device_create_file(&dev->dev,&dev_attr_irq);
+	device_create_file(&dev->dev,&dev_attr_resource);
 	return 0;
 }
 
diff -Nru a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
--- a/drivers/pcmcia/Makefile	Thu Aug  1 14:17:39 2002
+++ b/drivers/pcmcia/Makefile	Thu Aug  1 14:17:39 2002
@@ -2,7 +2,7 @@
 # Makefile for the kernel pcmcia subsystem (c/o David Hinds)
 #
 
-export-objs := ds.o cs.o yenta.o pci_socket.o
+export-objs := ds.o cs.o yenta.o
 
 obj-$(CONFIG_PCMCIA)			+= pcmcia_core.o ds.o
 ifeq ($(CONFIG_CARDBUS),y)
diff -Nru a/drivers/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c
--- a/drivers/pnp/pnpbios_core.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/pnp/pnpbios_core.c	Thu Aug  1 14:17:36 2002
@@ -124,13 +124,13 @@
 	".previous		\n"
 );
 
-#define Q_SET_SEL(selname, address, size) \
-set_base (gdt [(selname) >> 3], __va((u32)(address))); \
-set_limit (gdt [(selname) >> 3], size)
-
-#define Q2_SET_SEL(selname, address, size) \
-set_base (gdt [(selname) >> 3], (u32)(address)); \
-set_limit (gdt [(selname) >> 3], size)
+#define Q_SET_SEL(cpu, selname, address, size) \
+set_base(cpu_gdt_table[cpu][(selname) >> 3], __va((u32)(address))); \
+_set_limit(&cpu_gdt_table[cpu][(selname) >> 3], size)
+
+#define Q2_SET_SEL(cpu, selname, address, size) \
+set_base(cpu_gdt_table[cpu][(selname) >> 3], (u32)(address)); \
+_set_limit((char *)&cpu_gdt_table[cpu][(selname) >> 3], size)
 
 /*
  * At some point we want to use this stack frame pointer to unwind
@@ -161,10 +161,11 @@
 	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 	spin_lock_irqsave(&pnp_bios_lock, flags);
 
+	/* The lock prevents us bouncing CPU here */
 	if (ts1_size)
-		Q2_SET_SEL(PNP_TS1, ts1_base, ts1_size);
+		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
 	if (ts2_size)
-		Q2_SET_SEL(PNP_TS2, ts2_base, ts2_size);
+		Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
 
 	__asm__ __volatile__(
 	        "pushl %%ebp\n\t"
@@ -1265,12 +1266,16 @@
                        check->fields.version >> 4, check->fields.version & 15,
 		       check->fields.pm16cseg, check->fields.pm16offset,
 		       check->fields.pm16dseg);
-		Q2_SET_SEL(PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
-		Q_SET_SEL(PNP_CS16, check->fields.pm16cseg, 64 * 1024);
-		Q_SET_SEL(PNP_DS, check->fields.pm16dseg, 64 * 1024);
 		pnp_bios_callpoint.offset = check->fields.pm16offset;
 		pnp_bios_callpoint.segment = PNP_CS16;
 		pnp_bios_hdr = check;
+
+		for(i=0; i < NR_CPUS; i++)
+		{
+			Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024);
+			Q_SET_SEL(i, PNP_CS16, check->fields.pm16cseg, 64 * 1024);
+			Q_SET_SEL(i, PNP_DS, check->fields.pm16dseg, 64 * 1024);
+		}
 		break;
 	}
 	if (!pnp_bios_present())
diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
--- a/drivers/s390/block/dasd_genhd.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/s390/block/dasd_genhd.c	Thu Aug  1 14:17:41 2002
@@ -66,7 +66,6 @@
 	struct major_info *mi;
 	struct hd_struct *gd_part;
 	devfs_handle_t *gd_de_arr;
-	int *gd_sizes;
 	char *gd_flags;
 	int new_major, rc;
 
@@ -79,11 +78,10 @@
 			    GFP_KERNEL);
 	gd_flags = kmalloc(DASD_PER_MAJOR * sizeof(char), GFP_KERNEL);
 	gd_part = kmalloc(sizeof (struct hd_struct) << MINORBITS, GFP_ATOMIC);
-	gd_sizes = kmalloc(sizeof(int) << MINORBITS, GFP_ATOMIC);
 
 	/* Check if one of the allocations failed. */
 	if (mi == NULL || gd_de_arr == NULL || gd_flags == NULL ||
-	    gd_part == NULL || gd_sizes == NULL) {
+	    gd_part == NULL) {
 		MESSAGE(KERN_WARNING, "%s",
 			"Cannot get memory to allocate another "
 			"major number");
@@ -92,8 +90,7 @@
 	}
 
 	/* Register block device. */
-	new_major = devfs_register_blkdev(major, "dasd",
-					  &dasd_device_operations);
+	new_major = register_blkdev(major, "dasd", &dasd_device_operations);
 	if (new_major < 0) {
 		MESSAGE(KERN_WARNING,
 			"Cannot register to major no %d, rc = %d", major, rc);
@@ -113,17 +110,14 @@
 	mi->gendisk.de_arr = gd_de_arr;
 	mi->gendisk.flags = gd_flags;
 	mi->gendisk.part = gd_part;
-	mi->gendisk.sizes = gd_sizes;
 
 	/* Initialize the gendisk arrays. */
 	memset(gd_de_arr, 0, DASD_PER_MAJOR * sizeof(devfs_handle_t));
 	memset(gd_flags, 0, DASD_PER_MAJOR * sizeof (char));
 	memset(gd_part, 0, sizeof (struct hd_struct) << MINORBITS);
-	memset(gd_sizes, 0, sizeof(int) << MINORBITS);
 
 	/* Setup block device pointers for the new major. */
 	blk_dev[new_major].queue = dasd_get_queue;
-	blk_size[new_major] = gd_sizes;
 
 	/* Insert the new major info structure into dasd_major_info list. */
 	spin_lock(&dasd_major_lock);
@@ -137,7 +131,6 @@
 	/* Something failed. Do the cleanup and return rc. */
 out_error:
 	/* We rely on kfree to do the != NULL check. */
-	kfree(gd_sizes);
 	kfree(gd_part);
 	kfree(gd_flags);
 	kfree(gd_de_arr);
@@ -148,7 +141,6 @@
 static void
 dasd_unregister_major(struct major_info * mi)
 {
-	int *bs;
 	int major, rc;
 
 	if (mi == NULL)
@@ -165,17 +157,15 @@
 	/* Clear block device pointers. */
 	major = mi->gendisk.major;
 	blk_dev[major].queue = NULL;
-	bs = blk_size[major];
 	blk_clear(major);
 
-	rc = devfs_unregister_blkdev(major, "dasd");
+	rc = unregister_blkdev(major, "dasd");
 	if (rc < 0)
 		MESSAGE(KERN_WARNING,
 			"Cannot unregister from major no %d, rc = %d",
 			major, rc);
 
 	/* Free memory. */
-	kfree(bs);
 	kfree(mi->gendisk.part);
 	kfree(mi->gendisk.flags);
 	kfree(mi->gendisk.de_arr);
@@ -340,11 +330,6 @@
 		return;
 
 	wipe_partitions(device->kdev);
-
-	/* FIXME: do we really need that */
-	minor = minor(device->kdev);
-	for (i = 0; i < (1 << DASD_PARTN_BITS); i++)
-		gdp->sizes[minor + i] = 0;
 
 	/*
 	 * This is confusing. The funcions is devfs_register_partitions
diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
--- a/drivers/s390/block/dasd_ioctl.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/s390/block/dasd_ioctl.c	Thu Aug  1 14:17:36 2002
@@ -448,40 +448,6 @@
 }
 
 /*
- * Return device size in number of sectors.
- */
-static int dasd_ioctl_blkgetsize(void *inp, int no, long args)
-{
-	struct gendisk *gdp;
-	kdev_t kdev;
-	long blocks;
-
-	kdev = ((struct inode *) inp)->i_rdev;
-	gdp = dasd_gendisk_from_major(major(kdev));
-	if (gdp == NULL)
-		return -EINVAL;
-	blocks = gdp->sizes[minor(kdev)] << 1;
-	return put_user(blocks, (long *) args);
-}
-
-/*
- * Return device size in number of sectors, 64bit version.
- */
-static int dasd_ioctl_blkgetsize64(void *inp, int no, long args)
-{
-	struct gendisk *gdp;
-	kdev_t kdev;
-	u64 blocks;
-
-	kdev = ((struct inode *) inp)->i_rdev;
-	gdp = dasd_gendisk_from_major(major(kdev));
-	if (gdp == NULL)
-		return -EINVAL;
-	blocks = gdp->sizes[minor(kdev)] << 1;
-	return put_user(blocks << 10, (u64 *) args);
-}
-
-/*
  * Reread partition table.
  */
 static int dasd_ioctl_rr_partition(void *inp, int no, long args)
@@ -549,8 +515,6 @@
 	{ BIODASDINFO2, dasd_ioctl_information },
 	{ BIODASDPRRD, dasd_ioctl_read_profile },
 	{ BIODASDPRRST, dasd_ioctl_reset_profile },
-	{ BLKGETSIZE, dasd_ioctl_blkgetsize },
-	{ BLKGETSIZE64, dasd_ioctl_blkgetsize64 },
 	{ BLKROSET, dasd_ioctl_set_ro },
 	{ BLKRRPART, dasd_ioctl_rr_partition },
 	{ DASDAPIVER, dasd_ioctl_api_version },
diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c
--- a/drivers/s390/block/xpram.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/s390/block/xpram.c	Thu Aug  1 14:17:41 2002
@@ -449,7 +449,7 @@
 	/*
 	 * Register xpram major.
 	 */
-	rc = devfs_register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops);
+	rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops);
 	if (rc < 0) {
 		PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR);
 		return rc;
@@ -489,7 +489,7 @@
 static void __exit xpram_exit(void)
 {
 	blk_clear(XPRAM_MAJOR);
-	devfs_unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
+	unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
 	devfs_unregister(xpram_devfs_handle);
 	unregister_sys_device(&xpram_sys_device);
 }
diff -Nru a/drivers/s390/char/tapeblock.c b/drivers/s390/char/tapeblock.c
--- a/drivers/s390/char/tapeblock.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/s390/char/tapeblock.c	Thu Aug  1 14:17:41 2002
@@ -97,11 +97,7 @@
 	tape_dev_t* td;
 	tape_init();
 	/* Register the tape major number to the kernel */
-#ifdef CONFIG_DEVFS_FS
-	result = devfs_register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);
-#else
 	result = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);
-#endif
 	if (result < 0) {
 		PRINT_WARN(KERN_ERR "tape: can't get major %d for block device\n", tapeblock_major);
 		result=-ENODEV;
@@ -149,11 +145,7 @@
 out_undo_blk_size:
 	kfree(blk_size[tapeblock_major]);
 out_undo_bdev:
-#ifdef CONFIG_DEVFS_FS
-	devfs_unregister_blkdev(tapeblock_major, "tBLK");
-#else
 	unregister_blkdev(tapeblock_major, "tBLK");
-#endif
 	result=-ENOMEM;
 	blk_size[tapeblock_major]=
 	hardsect_size[tapeblock_major]=
@@ -181,11 +173,7 @@
 		max_sectors[tapeblock_major]=NULL;
 	}
 
-#ifdef CONFIG_DEVFS_FS
-	devfs_unregister_blkdev(tapeblock_major, "tBLK");
-#else
 	unregister_blkdev(tapeblock_major, "tBLK");
-#endif
 
 out:
 	return;
diff -Nru a/drivers/s390/char/tapechar.c b/drivers/s390/char/tapechar.c
--- a/drivers/s390/char/tapechar.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/s390/char/tapechar.c	Thu Aug  1 14:17:40 2002
@@ -128,11 +128,7 @@
 	tape_init();
 
 	/* Register the tape major number to the kernel */
-#ifdef CONFIG_DEVFS_FS
-	result = devfs_register_chrdev (tapechar_major, "tape", &tape_fops);
-#else
 	result = register_chrdev (tapechar_major, "tape", &tape_fops);
-#endif
 	if (result < 0) {
 		PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tapechar_major);
 		tape_sprintf_event (tape_dbf_area,3,"c:initfail\n");
@@ -178,11 +174,7 @@
 void
 tapechar_uninit (void)
 {
-#ifdef CONFIG_DEVFS_FS
-	devfs_unregister_chrdev (tapechar_major, "tape");
-#else
 	unregister_chrdev (tapechar_major, "tape");
-#endif
 }
 
 
diff -Nru a/drivers/s390/char/tubfs.c b/drivers/s390/char/tubfs.c
--- a/drivers/s390/char/tubfs.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/s390/char/tubfs.c	Thu Aug  1 14:17:40 2002
@@ -54,18 +54,15 @@
 void fs3270_devfs_unregister(tub_t *tubp)
 {
 	char name[16];
-	devfs_handle_t handle;
 
 	sprintf(name, "tub%.4x", tubp->devno);
-	handle = devfs_find_handle (fs3270_devfs_dir, name,
-				    IBM_FS3270_MAJOR, tubp->minor,
-				    DEVFS_SPECIAL_CHR, 0);
-	devfs_unregister (handle);
+	devfs_find_and_unregister(fs3270_devfs_dir, name,
+				  IBM_FS3270_MAJOR, tubp->minor,
+				  DEVFS_SPECIAL_CHR, 0);
 	sprintf(name, "tty%.4x", tubp->devno);
-	handle = devfs_find_handle (fs3270_devfs_dir, name,
-				    IBM_TTY3270_MAJOR, tubp->minor,
-				    DEVFS_SPECIAL_CHR, 0);
-	devfs_unregister(handle);
+	devfs_find_and_unregister(fs3270_devfs_dir, name,
+				  IBM_TTY3270_MAJOR, tubp->minor,
+				  DEVFS_SPECIAL_CHR, 0);
 }
 #endif
 
@@ -77,26 +74,19 @@
 {
 	int rc;
 
-#ifdef CONFIG_DEVFS_FS
-	rc = devfs_register_chrdev (IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
+	rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
 	if (rc) {
 		printk(KERN_ERR "tubmod can't get major nbr %d: error %d\n",
 			IBM_FS3270_MAJOR, rc);
 		return -1;
 	}
+#ifdef CONFIG_DEVFS_FS
 	fs3270_devfs_dir = devfs_mk_dir(NULL, "3270", NULL);
 	fs3270_devfs_tub = 
 		devfs_register(fs3270_devfs_dir, "tub", DEVFS_FL_DEFAULT,
 			       IBM_FS3270_MAJOR, 0,
 			       S_IFCHR | S_IRUGO | S_IWUGO, 
 			       &fs3270_fops, NULL);
-#else
-	rc = register_chrdev(IBM_FS3270_MAJOR, "fs3270", &fs3270_fops);
-	if (rc) {
-		printk(KERN_ERR "tubmod can't get major nbr %d: error %d\n",
-			IBM_FS3270_MAJOR, rc);
-		return -1;
-	}
 #endif
 	fs3270_major = IBM_FS3270_MAJOR;
 	return 0;
diff -Nru a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile
--- a/drivers/s390/cio/Makefile	Thu Aug  1 14:17:36 2002
+++ b/drivers/s390/cio/Makefile	Thu Aug  1 14:17:36 2002
@@ -8,6 +8,6 @@
 obj-$(CONFIG_CHSC) += chsc.o
 obj-$(CONFIG_PROC_FS) += proc.o
 
-export-objs += airq.o cio.o ioinfo.o misc.o requestirq.o s390io.o
+export-objs += airq.o cio.o ioinfo.o requestirq.o s390io.o
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c
--- a/drivers/sbus/audio/audio.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/sbus/audio/audio.c	Thu Aug  1 14:17:36 2002
@@ -2077,7 +2077,6 @@
 
 int unregister_sparcaudio_driver(struct sparcaudio_driver *drv, int duplex)
 {
-	devfs_handle_t de;
 	int i;
 	char name_buf[32];
 
@@ -2104,9 +2103,8 @@
 	/* Unregister ourselves with devfs */
 	for (i=0; i < sizeof (dev_list) / sizeof (*dev_list); i++) {
 		sparcaudio_mkname (name_buf, dev_list[i].name, drv->index);
-		de = devfs_find_handle (devfs_handle, name_buf, 0, 0,
-					DEVFS_SPECIAL_CHR, 0);
-		devfs_unregister (de);
+		devfs_find_and_unregister(devfs_handle, name_buf, 0, 0,
+                                          DEVFS_SPECIAL_CHR, 0);
 	}
 
 	MOD_DEC_USE_COUNT;
@@ -2125,7 +2123,7 @@
 static int __init sparcaudio_init(void)
 {
 	/* Register our character device driver with the VFS. */
-	if (devfs_register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops))
+	if (register_chrdev(SOUND_MAJOR, "sparcaudio", &sparcaudio_fops))
 		return -EIO;
 
 	devfs_handle = devfs_mk_dir (NULL, "sound", NULL);
@@ -2134,7 +2132,7 @@
 
 static void __exit sparcaudio_exit(void)
 {
-	devfs_unregister_chrdev(SOUND_MAJOR, "sparcaudio");
+	unregister_chrdev(SOUND_MAJOR, "sparcaudio");
 	devfs_unregister (devfs_handle);
 }
 
diff -Nru a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c
--- a/drivers/sbus/char/bpp.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/sbus/char/bpp.c	Thu Aug  1 14:17:36 2002
@@ -1041,7 +1041,7 @@
 	if (rc == 0)
 		return -ENODEV;
 
-	rc = devfs_register_chrdev(BPP_MAJOR, dev_name, &bpp_fops);
+	rc = register_chrdev(BPP_MAJOR, dev_name, &bpp_fops);
 	if (rc < 0)
 		return rc;
 
@@ -1062,7 +1062,7 @@
 	unsigned idx;
 
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev(BPP_MAJOR, dev_name);
+	unregister_chrdev(BPP_MAJOR, dev_name);
 
 	for (idx = 0 ;  idx < BPP_NO ;  idx += 1) {
 		if (instances[idx].present)
diff -Nru a/drivers/sbus/char/sunkbd.c b/drivers/sbus/char/sunkbd.c
--- a/drivers/sbus/char/sunkbd.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/sbus/char/sunkbd.c	Thu Aug  1 14:17:41 2002
@@ -1615,7 +1615,7 @@
 			KBD_MAJOR, 0,
 			S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH,
 			&kbd_fops, NULL);
-	if (devfs_register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){
+	if (register_chrdev (KBD_MAJOR, "kbd", &kbd_fops)){
 		printk ("Could not register /dev/kbd device\n");
 		return;
 	}
diff -Nru a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c
--- a/drivers/sbus/char/vfc_dev.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/sbus/char/vfc_dev.c	Thu Aug  1 14:17:40 2002
@@ -676,7 +676,7 @@
 	memset(vfc_dev_lst, 0, sizeof(struct vfc_dev *) * (cards + 1));
 	vfc_dev_lst[cards] = NULL;
 
-	ret = devfs_register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops);
+	ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops);
 	if(ret) {
 		printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR);
 		kfree(vfc_dev_lst);
@@ -732,7 +732,7 @@
 {
 	struct vfc_dev **devp;
 
-	devfs_unregister_chrdev(VFC_MAJOR,vfcstr);
+	unregister_chrdev(VFC_MAJOR,vfcstr);
 
 	for (devp = vfc_dev_lst; *devp; devp++)
 		deinit_vfc_device(*devp);
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/scsi/ide-scsi.c	Thu Aug  1 14:17:36 2002
@@ -1,33 +1,12 @@
 /*
  * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
- */
-/*
+ *
  * Emulation of a SCSI host adapter for IDE ATAPI devices.
  *
  * With this driver, one can use the Linux SCSI drivers instead of the
  * native IDE ATAPI drivers.
- *
- * Ver 0.1   Dec  3 96   Initial version.
- * Ver 0.2   Jan 26 97   Fixed bug in cleanup_module() and added emulation
- *                        of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks
- *                        to Janos Farkas for pointing this out.
- *                       Avoid using bitfields in structures for m68k.
- *                       Added Scatter/Gather and DMA support.
- * Ver 0.4   Dec  7 97   Add support for ATAPI PD/CD drives.
- *                       Use variable timeout for each command.
- * Ver 0.5   Jan  2 98   Fix previous PD/CD support.
- *                       Allow disabling of SCSI-6 to SCSI-10 transformation.
- * Ver 0.6   Jan 27 98   Allow disabling of SCSI command translation layer
- *                        for access through /dev/sg.
- *                       Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
- * Ver 0.7   Dec 04 98   Ignore commands where lun != 0 to avoid multiple
- *                        detection of devices with CONFIG_SCSI_MULTI_LUN
- * Ver 0.8   Feb 05 99   Optical media need translation too. Reverse 0.7.
- * Ver 0.9   Jul 04 99   Fix a bug in SG_SET_TRANSFORM.
  */
 
-#define IDESCSI_VERSION "0.9"
-
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -495,9 +474,8 @@
 static Scsi_Host_Template template;
 static int idescsi_cleanup (struct ata_device *drive)
 {
-	if (ide_unregister_subdriver (drive)) {
+	if (ata_unregister_device(drive))
 		return 1;
-	}
 	scsi_unregister_host(&template);
 
 	return 0;
@@ -762,7 +740,7 @@
 
 	host = scsi_register(&template, sizeof(idescsi_scsi_t));
 	if (!host) {
-		printk (KERN_ERR
+		printk(KERN_ERR
 			"ide-scsi: %s: Can't allocate a scsi host structure\n",
 			drive->name);
 		return;
@@ -771,8 +749,8 @@
 	host->max_lun = drive->last_lun + 1;
 	host->max_id = 1;
 
-	if (ide_register_subdriver(drive, &ata_ops)) {
-		printk (KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
+	if (ata_register_device(drive, &ata_ops)) {
+		printk(KERN_ERR "ide-scsi: %s: Failed to register the driver with ide.c\n", drive->name);
 		scsi_unregister(host);
 		return;
 	}
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/scsi/osst.c	Thu Aug  1 14:17:40 2002
@@ -5585,11 +5585,7 @@
   if (osst_template.dev_noticed == 0) return 0;
 
   if(!osst_registered) {
-#ifdef CONFIG_DEVFS_FS
-	if (devfs_register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
-#else
 	if (register_chrdev(MAJOR_NR,"osst",&osst_fops)) {
-#endif
 		printk(KERN_ERR "osst :W: Unable to get major %d for OnStream tapes\n",MAJOR_NR);
 		return 1;
 	}
@@ -5605,11 +5601,7 @@
 				   GFP_ATOMIC);
   if (os_scsi_tapes == NULL) {
 	printk(KERN_ERR "osst :W: Unable to allocate array for OnStream SCSI tapes.\n");
-#ifdef CONFIG_DEVFS_FS
-	devfs_unregister_chrdev(MAJOR_NR, "osst");
-#else
 	unregister_chrdev(MAJOR_NR, "osst");
-#endif
 	return 1;
   }
 
@@ -5621,11 +5613,7 @@
 				    GFP_ATOMIC);
   if (osst_buffers == NULL) {
 	printk(KERN_ERR "osst :W: Unable to allocate tape buffer pointers.\n");
-#ifdef CONFIG_DEVFS_FS
-	devfs_unregister_chrdev(MAJOR_NR, "osst");
-#else
 	unregister_chrdev(MAJOR_NR, "osst");
-#endif
 	kfree(os_scsi_tapes);
 	return 1;
   }
@@ -5684,11 +5672,7 @@
   OS_Scsi_Tape * STp;
 
   scsi_unregister_device(&osst_template);
-#ifdef CONFIG_DEVFS_FS
-  devfs_unregister_chrdev(MAJOR_NR, "osst");
-#else
   unregister_chrdev(MAJOR_NR, "osst");
-#endif
   osst_registered--;
   if(os_scsi_tapes != NULL) {
 	for (i=0; i < osst_template.dev_max; ++i) {
diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
--- a/drivers/scsi/scsi_error.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/scsi/scsi_error.c	Thu Aug  1 14:17:36 2002
@@ -1878,6 +1878,7 @@
 	 */
 
 	daemonize();
+	reparent_to_init();
 
 	/*
 	 * Set the name of this process.
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/scsi/scsi_scan.c	Thu Aug  1 14:17:41 2002
@@ -305,12 +305,8 @@
 
 	return 0;
 }
+static DEVICE_ATTR(type,"type",S_IRUGO,scsi_device_type_read,NULL);
 
-static struct driver_file_entry scsi_device_type_file = {
-	name: "type",
-	mode: S_IRUGO,
-	show: scsi_device_type_read,
-};
 /* end content handlers */
 
 static void print_inquiry(unsigned char *data)
@@ -715,7 +711,7 @@
 
 		scsi_wait_req (SRpnt, (void *) scsi_cmd,
 			  (void *) scsi_result,
-			  256, SCSI_TIMEOUT+4*HZ, 3);
+			  scsi_cmd[4], SCSI_TIMEOUT+4*HZ, 3);
 		/* assume successful */
 	}
 	SDpnt->inquiry_len = possible_inq_resp_len;
@@ -825,7 +821,7 @@
 
 	/* Create driverfs file entries */
 	device_create_file(&SDpnt->sdev_driverfs_dev, 
-			&scsi_device_type_file);
+			   &dev_attr_type);
 
         sprintf (devname, "host%d/bus%d/target%d/lun%d",
                  SDpnt->host->host_no, SDpnt->channel, SDpnt->id, SDpnt->lun);
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Thu Aug  1 14:17:37 2002
+++ b/drivers/scsi/sd.c	Thu Aug  1 14:17:37 2002
@@ -90,9 +90,6 @@
 static Scsi_Disk ** sd_dsk_arr;
 static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
 
-static int *sd_sizes;
-static int *sd_max_sectors;
-
 static int check_scsidisk_media_change(kdev_t);
 static int fop_revalidate_scsidisk(kdev_t);
 
@@ -536,7 +533,7 @@
 	 * See if we are requesting a non-existent partition.  Do this
 	 * after checking for disk change.
 	 */
-	if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0) {
+	if (sd[SD_PARTITION(inode->i_rdev)].nr_sects == 0) {
 		goto error_out;
 	}
 
@@ -606,22 +603,7 @@
 	revalidate:		fop_revalidate_scsidisk
 };
 
-/*
- *    If we need more than one SCSI disk major (i.e. more than
- *      16 SCSI disks), we'll have to vmalloc() more gendisks later.
- */
-
-static struct gendisk sd_gendisk =
-{
-	major:		SCSI_DISK0_MAJOR,
-	major_name:	"sd",
-	minor_shift:	4,
-	fops:		&sd_fops,
-};
-
-static struct gendisk *sd_gendisks = &sd_gendisk;
-
-#define SD_GENDISK(i)    sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
+static struct gendisk **sd_disks;
 
 /**
  *	sd_rw_intr - bottom half handler: called when the lower level
@@ -1077,7 +1059,7 @@
 	SRpnt->sr_data_direction = SCSI_DATA_READ;
 
 	scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
-		      512, SD_TIMEOUT, MAX_RETRIES);
+		      255, SD_TIMEOUT, MAX_RETRIES);
 
 	the_result = SRpnt->sr_result;
 
@@ -1198,8 +1180,7 @@
 
 	if (!sd_registered) {
 		for (k = 0; k < N_USED_SD_MAJORS; k++) {
-			if (devfs_register_blkdev(SD_MAJOR(k), "sd",
-						  &sd_fops)) {
+			if (register_blkdev(SD_MAJOR(k), "sd", &sd_fops)) {
 				printk(KERN_NOTICE "Unable to get major %d "
 				       "for SCSI disk\n", SD_MAJOR(k));
 				return 1;
@@ -1226,69 +1207,25 @@
 			sd_dsk_arr[k] = sdkp;
 		}
 	}
-	init_mem_lth(sd_sizes, maxparts);
+	init_mem_lth(sd_disks, sd_template.dev_max);
+	if (sd_disks)
+		zero_mem_lth(sd_disks, sd_template.dev_max);
 	init_mem_lth(sd, maxparts);
-	init_mem_lth(sd_gendisks, N_USED_SD_MAJORS);
-	init_mem_lth(sd_max_sectors, sd_template.dev_max << 4);
 
-	if (!sd_dsk_arr || !sd_sizes || !sd || !sd_gendisks)
+	if (!sd_dsk_arr || !sd || !sd_disks)
 		goto cleanup_mem;
 
-	zero_mem_lth(sd_sizes, maxparts);
 	zero_mem_lth(sd, maxparts);
-
-	for (k = 0; k < maxparts; k++) {
-		/*
-		 * Allow lowlevel device drivers to generate 512k large scsi
-		 * commands if they know what they're doing and they ask for it
-		 * explicitly via the SHpnt->max_sectors API.
-		 */
-		sd_max_sectors[k] = MAX_PHYS_SEGMENTS*8;
-	}
-
-	for (k = 0; k < N_USED_SD_MAJORS; k++) {
-		int N = SCSI_DISKS_PER_MAJOR;
-
-		sd_gendisks[k] = sd_gendisk;
-
-		init_mem_lth(sd_gendisks[k].de_arr, N);
-		init_mem_lth(sd_gendisks[k].flags, N);
-		init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
-
-		if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags ||
-				!sd_gendisks[k].driverfs_dev_arr)
-			goto cleanup_gendisks;
-
-		zero_mem_lth(sd_gendisks[k].de_arr, N);
-		zero_mem_lth(sd_gendisks[k].flags, N);
-		zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
-
-		sd_gendisks[k].major = SD_MAJOR(k);
-		sd_gendisks[k].major_name = "sd";
-		sd_gendisks[k].minor_shift = 4;
-		sd_gendisks[k].part = sd + k * (N << 4);
-		sd_gendisks[k].sizes = sd_sizes + k * (N << 4);
-		sd_gendisks[k].nr_real = 0;
-	}
 	return 0;
 
 #undef init_mem_lth
 #undef zero_mem_lth
 
-cleanup_gendisks:
-	/* vfree can handle NULL, so no test is required here */
-	for (k = 0; k < N_USED_SD_MAJORS; k++) {
-		vfree(sd_gendisks[k].de_arr);
-		vfree(sd_gendisks[k].flags);
-		vfree(sd_gendisks[k].driverfs_dev_arr);
-	}
 cleanup_mem:
-	vfree(sd_gendisks);
-	sd_gendisks = NULL;
+	vfree(sd_disks);
+	sd_disks = NULL;
 	vfree(sd);
 	sd = NULL;
-	vfree(sd_sizes);
-	sd_sizes = NULL;
 	if (sd_dsk_arr) {
                 for (k = 0; k < sd_template.dev_max; ++k)
 			vfree(sd_dsk_arr[k]);
@@ -1296,7 +1233,7 @@
 		sd_dsk_arr = NULL;
 	}
 	for (k = 0; k < N_USED_SD_MAJORS; k++) {
-		devfs_unregister_blkdev(SD_MAJOR(k), "sd");
+		unregister_blkdev(SD_MAJOR(k), "sd");
 	}
 	sd_registered--;
 	return 1;
@@ -1317,18 +1254,16 @@
 	Scsi_Disk * sdkp;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n"));
-	for (k = 0; k < N_USED_SD_MAJORS; k++) {
+	for (k = 0; k < N_USED_SD_MAJORS; k++)
 		blk_dev[SD_MAJOR(k)].queue = sd_find_queue;
-		add_gendisk(&(sd_gendisks[k]));
-	}
 
 	for (k = 0; k < sd_template.dev_max; ++k) {
 		sdkp = sd_get_sdisk(k);
 		if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
 			sd_init_onedisk(sdkp, k);
 			if (!sdkp->has_been_registered) {
-				sd_sizes[k << 4] = sdkp->capacity;
-				register_disk(&SD_GENDISK(k), MKDEV_SD(k),
+				add_gendisk(sd_disks[k]);
+				register_disk(sd_disks[k], MKDEV_SD(k),
 						1<<4, &sd_fops,
 						sdkp->capacity);
 				sdkp->has_been_registered = 1;
@@ -1374,21 +1309,36 @@
  **/
 static int sd_attach(Scsi_Device * sdp)
 {
-        unsigned int devnum;
 	Scsi_Disk *sdkp;
 	int dsk_nr;
 	char diskname[6];
 	unsigned long iflags;
+	struct {
+		struct gendisk disk;
+		devfs_handle_t de;
+		struct device *dev;
+		char flags;
+	} *p;
+	struct gendisk *gd;
 
 	if ((NULL == sdp) ||
 	    ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)))
 		return 0;
 
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return 1;
+	gd = &p->disk;
+	gd->de_arr = &p->de;
+	gd->flags = &p->flags;
+	gd->driverfs_dev_arr = &p->dev;
+
 	SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", 
 			 sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
 	if (sd_template.nr_dev >= sd_template.dev_max) {
 		sdp->attached--;
 		printk(KERN_ERR "sd_init: no more room for device\n");
+		kfree(p);
 		return 1;
 	}
 
@@ -1408,17 +1358,23 @@
 	if (dsk_nr >= sd_template.dev_max) {
 		/* panic("scsi_devices corrupt (sd)");  overkill */
 		printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n");
+		kfree(p);
 		return 1;
 	}
 
 	sd_template.nr_dev++;
-	SD_GENDISK(dsk_nr).nr_real++;
-        devnum = dsk_nr % SCSI_DISKS_PER_MAJOR;
-        SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
-        SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] = 
-		&sdp->sdev_driverfs_dev;
+	gd->nr_real = 1;
+        gd->de_arr[0] = sdp->de;
+        gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev;
+	gd->major = SD_MAJOR(dsk_nr>>4);
+	gd->first_minor = (dsk_nr & 15)<<4;
+	gd->major_name = "sd";
+	gd->minor_shift = 4;
+	gd->part = sd + (dsk_nr << 4);
+	gd->fops = &sd_fops;
         if (sdp->removable)
-		SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
+		gd->flags[0] |= GENHD_FL_REMOVABLE;
+	sd_disks[dsk_nr] = gd;
 	sd_dskname(dsk_nr, diskname);
 	printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
 	       "id %d, lun %d\n", sdp->removable ? "removable " : "",
@@ -1487,9 +1443,7 @@
 {
 	Scsi_Disk *sdkp = NULL;
 	kdev_t dev;
-	int dsk_nr, j;
-	int max_p;
-	int start;
+	int dsk_nr;
 	unsigned long iflags;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n", 
@@ -1499,7 +1453,6 @@
 	for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
 		sdkp = sd_dsk_arr[dsk_nr];
 		if (sdkp->device == sdp) {
-			sdkp->has_been_registered = 0;
 			sdkp->device = NULL;
 			sdkp->capacity = 0;
 			/* sdkp->detaching = 1; */
@@ -1510,22 +1463,20 @@
 	if (dsk_nr >= sd_template.dev_max)
 		return;
 
-	max_p = 1 << sd_gendisk.minor_shift;
-	start = dsk_nr << sd_gendisk.minor_shift;
-	dev = MKDEV_SD_PARTITION(start);
-	driverfs_remove_partitions(&SD_GENDISK (dsk_nr), 
-					SD_MINOR_NUMBER (start));
-	wipe_partitions(dev);
-	for (j = max_p - 1; j >= 0; j--)
-		sd_sizes[start + j] = 0;
-
-	devfs_register_partitions (&SD_GENDISK (dsk_nr),
-				   SD_MINOR_NUMBER (start), 1);
-	/* unregister_disk() */
+	if (sdkp->has_been_registered) {
+		sdkp->has_been_registered = 0;
+		dev = MKDEV_SD(dsk_nr);
+		driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev));
+		wipe_partitions(dev);
+		devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1);
+		/* unregister_disk() */
+		del_gendisk(sd_disks[dsk_nr]);
+	}
 	sdp->attached--;
 	sd_template.dev_noticed--;
 	sd_template.nr_dev--;
-	SD_GENDISK(dsk_nr).nr_real--;
+	kfree(sd_disks[dsk_nr]);
+	sd_disks[dsk_nr] = NULL;
 }
 
 /**
@@ -1560,7 +1511,7 @@
 	SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n"));
 	scsi_unregister_device(&sd_template);
 	for (k = 0; k < N_USED_SD_MAJORS; k++)
-		devfs_unregister_blkdev(SD_MAJOR(k), "sd");
+		unregister_blkdev(SD_MAJOR(k), "sd");
 
 	sd_registered--;
 	if (sd_dsk_arr != NULL) {
@@ -1568,16 +1519,12 @@
 			vfree(sd_dsk_arr[k]);
 		vfree(sd_dsk_arr);
 	}
-	vfree(sd_sizes);
 	vfree((char *) sd);
 	for (k = 0; k < N_USED_SD_MAJORS; k++) {
 		blk_dev[SD_MAJOR(k)].queue = NULL;
-		del_gendisk(&(sd_gendisks[k]));
 		blk_clear(SD_MAJOR(k));
 	}
 	sd_template.dev_max = 0;
-	if (sd_gendisks != &sd_gendisk)
-		vfree(sd_gendisks);
 	remove_driver(&sd_template.scsi_driverfs_driver);
 }
 
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/scsi/sg.c	Thu Aug  1 14:17:40 2002
@@ -1348,8 +1348,7 @@
 
     write_lock_irqsave(&sg_dev_arr_lock, iflags);
     if(!sg_registered) {
-	if (devfs_register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
-        {
+	if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) {
             printk(KERN_ERR "Unable to get major %d for generic SCSI device\n",
                    SCSI_GENERIC_MAJOR);
 	    write_unlock_irqrestore(&sg_dev_arr_lock, iflags);
@@ -1402,22 +1401,14 @@
 	Sg_device * sdp=list_entry(driverfs_dev, Sg_device, sg_driverfs_dev);
 	return off ? 0 : sprintf(page, "%x\n",sdp->i_rdev.value);
 }
-static struct driver_file_entry sg_device_kdev_file = {
-	name: "kdev",
-	mode: S_IRUGO,
-	show: sg_device_kdev_read,
-};
+static DEVICE_ATTR(kdev,"kdev",S_IRUGO,sg_device_kdev_read,NULL);
 
 static ssize_t sg_device_type_read(struct device *driverfs_dev, char *page, 
 		size_t count, loff_t off) 
 {
 	return off ? 0 : sprintf (page, "CHR\n");
 }
-static struct driver_file_entry sg_device_type_file = {
-	name: "type",
-	mode: S_IRUGO,
-	show: sg_device_type_read,
-};
+static DEVICE_ATTR(type,"type",S_IRUGO,sg_device_type_read,NULL);
 
 static int sg_attach(Scsi_Device * scsidp)
 {
@@ -1485,8 +1476,8 @@
     sdp->sg_driverfs_dev.parent = &scsidp->sdev_driverfs_dev;
     sdp->sg_driverfs_dev.bus = &scsi_driverfs_bus_type;
     device_register(&sdp->sg_driverfs_dev);
-    device_create_file(&sdp->sg_driverfs_dev, &sg_device_type_file);
-    device_create_file(&sdp->sg_driverfs_dev, &sg_device_kdev_file);
+    device_create_file(&sdp->sg_driverfs_dev, &dev_attr_type);
+    device_create_file(&sdp->sg_driverfs_dev, &dev_attr_kdev);
 
     sdp->de = devfs_register (scsidp->de, "generic", DEVFS_FL_DEFAULT,
                              SCSI_GENERIC_MAJOR, k,
@@ -1556,8 +1547,8 @@
             }
 	    SCSI_LOG_TIMEOUT(3, printk("sg_detach: dev=%d, dirty\n", k));
 	    devfs_unregister (sdp->de);
-	    device_remove_file(&sdp->sg_driverfs_dev,sg_device_type_file.name);
-	    device_remove_file(&sdp->sg_driverfs_dev,sg_device_kdev_file.name);
+	    device_remove_file(&sdp->sg_driverfs_dev,&dev_attr_type);
+	    device_remove_file(&sdp->sg_driverfs_dev,&dev_attr_kdev);
 	    put_device(&sdp->sg_driverfs_dev);
 	    sdp->de = NULL;
 	    if (NULL == sdp->headfp) {
@@ -1611,7 +1602,7 @@
     sg_proc_cleanup();
 #endif  /* CONFIG_PROC_FS */
     scsi_unregister_device(&sg_template);
-    devfs_unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
+    unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
     if(sg_dev_arr != NULL) {
 	kfree((char *)sg_dev_arr);
         sg_dev_arr = NULL;
diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c
--- a/drivers/scsi/sr.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/scsi/sr.c	Thu Aug  1 14:17:39 2002
@@ -702,7 +702,7 @@
 		return 0;
 
 	if (!sr_registered) {
-		if (devfs_register_blkdev(MAJOR_NR, "sr", &sr_bdops)) {
+		if (register_blkdev(MAJOR_NR, "sr", &sr_bdops)) {
 			printk("Unable to get major %d for SCSI-CD\n", MAJOR_NR);
 			return 1;
 		}
@@ -714,7 +714,7 @@
 	sr_template.dev_max = sr_template.dev_noticed + SR_EXTRA_DEVS;
 	scsi_CDs = kmalloc(sr_template.dev_max * sizeof(Scsi_CD), GFP_ATOMIC);
 	if (!scsi_CDs)
-		goto cleanup_devfs;
+		goto cleanup_dev;
 	memset(scsi_CDs, 0, sr_template.dev_max * sizeof(Scsi_CD));
 
 	sr_sizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
@@ -725,8 +725,8 @@
 
 cleanup_cds:
 	kfree(scsi_CDs);
-cleanup_devfs:
-	devfs_unregister_blkdev(MAJOR_NR, "sr");
+cleanup_dev:
+	unregister_blkdev(MAJOR_NR, "sr");
 	sr_registered--;
 	return 1;
 }
@@ -739,22 +739,14 @@
 	kdev.value=(int)driverfs_dev->driver_data;
 	return off ? 0 : sprintf(page, "%x\n",kdev.value);
 }
-static struct driver_file_entry sr_device_kdev_file = {
-	name: "kdev",
-	mode: S_IRUGO,
-	show: sr_device_kdev_read,
-};
+static DEVICE_ATTR(kdev,"kdev",S_IRUGO,sr_device_kdev_read,NULL);
 
 static ssize_t sr_device_type_read(struct device *driverfs_dev, 
 				   char *page, size_t count, loff_t off) 
 {
 	return off ? 0 : sprintf (page, "CHR\n");
 }
-static struct driver_file_entry sr_device_type_file = {
-	name: "type",
-	mode: S_IRUGO,
-	show: sr_device_type_read,
-};
+static DEVICE_ATTR(type,"type",S_IRUGO,sr_device_type_read,NULL);
 
 
 void sr_finish()
@@ -813,9 +805,9 @@
 			(void *)__mkdev(MAJOR_NR, i);
 		device_register(&SCp->cdi.cdrom_driverfs_dev);
 		device_create_file(&SCp->cdi.cdrom_driverfs_dev,
-				&sr_device_type_file);
+				   &dev_attr_type);
 		device_create_file(&SCp->cdi.cdrom_driverfs_dev,
-				&sr_device_kdev_file);
+				   &dev_attr_kdev);
                 SCp->cdi.de = devfs_register(SCp->device->de, "cd",
                                     DEVFS_FL_DEFAULT, MAJOR_NR, i,
                                     S_IFBLK | S_IRUGO | S_IWUGO,
@@ -869,7 +861,7 @@
 static void __exit exit_sr(void)
 {
 	scsi_unregister_device(&sr_template);
-	devfs_unregister_blkdev(MAJOR_NR, "sr");
+	unregister_blkdev(MAJOR_NR, "sr");
 	sr_registered--;
 	if (scsi_CDs != NULL) {
 		kfree(scsi_CDs);
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/scsi/st.c	Thu Aug  1 14:17:41 2002
@@ -3533,22 +3533,14 @@
 	kdev.value=(int)driverfs_dev->driver_data;
 	return off ? 0 : sprintf(page, "%x\n",kdev.value);
 }
-static struct driver_file_entry st_device_kdev_file = {
-	name: "kdev",
-	mode: S_IRUGO,
-	show: st_device_kdev_read,
-};
+static DEVICE_ATTR(kdev,"kdev",S_IRUGO,st_device_kdev_read,NULL);
 
 static ssize_t st_device_type_read(struct device *driverfs_dev, 
 				   char *page, size_t count, loff_t off) 
 {
 	return off ? 0 : sprintf (page, "CHR\n");
 }
-static struct driver_file_entry st_device_type_file = {
-	name: "type",
-	mode: S_IRUGO,
-	show: st_device_type_read,
-};
+static DEVICE_ATTR(type,"type",S_IRUGO,st_device_type_read,NULL);
 
 
 static struct file_operations st_fops =
@@ -3664,8 +3656,8 @@
 			(void *)__mkdev(MAJOR_NR, i + (mode << 5));
 	    device_register(&tpnt->driverfs_dev_r[mode]);
 	    device_create_file(&tpnt->driverfs_dev_r[mode], 
-			       &st_device_type_file);
-	    device_create_file(&tpnt->driverfs_dev_r[mode], &st_device_kdev_file);
+			       &dev_attr_type);
+	    device_create_file(&tpnt->driverfs_dev_r[mode], &dev_attr_kdev);
 	    tpnt->de_r[mode] =
 		devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
 				MAJOR_NR, i + (mode << 5),
@@ -3683,9 +3675,9 @@
 			(void *)__mkdev(MAJOR_NR, i + (mode << 5) + 128);
 	    device_register(&tpnt->driverfs_dev_n[mode]);
 	    device_create_file(&tpnt->driverfs_dev_n[mode], 
-			&st_device_type_file);
+			       &dev_attr_type);
 	    device_create_file(&tpnt->driverfs_dev_n[mode], 
-			&st_device_kdev_file);
+			       &dev_attr_kdev);
 	    tpnt->de_n[mode] =
 		devfs_register (SDp->de, name, DEVFS_FL_DEFAULT,
 				MAJOR_NR, i + (mode << 5) + 128,
@@ -3785,16 +3777,16 @@
 				devfs_unregister (tpnt->de_r[mode]);
 				tpnt->de_r[mode] = NULL;
 				device_remove_file(&tpnt->driverfs_dev_r[mode],
-						   st_device_type_file.name);
+						   &dev_attr_type);
 				device_remove_file(&tpnt->driverfs_dev_r[mode],
-						   st_device_kdev_file.name);
+						   &dev_attr_type);
 				put_device(&tpnt->driverfs_dev_r[mode]);
 				devfs_unregister (tpnt->de_n[mode]);
 				tpnt->de_n[mode] = NULL;
 				device_remove_file(&tpnt->driverfs_dev_n[mode],
-						   st_device_type_file.name);
+						   &dev_attr_type);
 				device_remove_file(&tpnt->driverfs_dev_n[mode],
-						   st_device_kdev_file.name);
+						   &dev_attr_kdev);
 				put_device(&tpnt->driverfs_dev_n[mode]);
 			}
 			if (tpnt->buffer) {
@@ -3826,7 +3818,7 @@
 		verstr, st_fixed_buffer_size, st_write_threshold,
 		st_max_sg_segs);
 
-	if (devfs_register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
+	if (register_chrdev(SCSI_TAPE_MAJOR, "st", &st_fops) >= 0) {
 		if (scsi_register_device(&st_template) == 0) {
 			st_template.scsi_driverfs_driver.name = 
 				(char *)st_template.tag;
@@ -3846,7 +3838,7 @@
 	int i;
 
 	scsi_unregister_device(&st_template);
-	devfs_unregister_chrdev(SCSI_TAPE_MAJOR, "st");
+	unregister_chrdev(SCSI_TAPE_MAJOR, "st");
 	if (scsi_tapes != NULL) {
 		for (i=0; i < st_template.dev_max; ++i)
 			if (scsi_tapes[i])
diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c
--- a/drivers/serial/21285.c	Thu Aug  1 14:17:37 2002
+++ b/drivers/serial/21285.c	Thu Aug  1 14:17:37 2002
@@ -5,29 +5,19 @@
  *
  * Based on drivers/char/serial.c
  *
- *  $Id: 21285.c,v 1.34 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: 21285.c,v 1.37 2002/07/28 10:03:27 rmk Exp $
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/console.h>
 #include <linux/serial_core.h>
+#include <linux/serial.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
 #include <asm/hardware/dec21285.h>
 #include <asm/hardware.h>
 
@@ -85,14 +75,10 @@
 
 static void serial21285_stop_rx(struct uart_port *port)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
 	if (rx_enabled(port)) {
 		disable_irq(IRQ_CONRX);
 		rx_enabled(port) = 0;
 	}
-	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void serial21285_enable_ms(struct uart_port *port)
@@ -514,7 +500,7 @@
 {
 	int ret;
 
-	printk(KERN_INFO "Serial: 21285 driver $Revision: 1.34 $\n");
+	printk(KERN_INFO "Serial: 21285 driver $Revision: 1.37 $\n");
 
 	serial21285_setup_ports();
 
@@ -537,4 +523,4 @@
 EXPORT_NO_SYMBOLS;
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.34 $");
+MODULE_DESCRIPTION("Intel Footbridge (21285) serial driver $Revision: 1.37 $");
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/serial/8250.c	Thu Aug  1 14:17:36 2002
@@ -12,7 +12,7 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  *
- *  $Id: 8250.c,v 1.84 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: 8250.c,v 1.90 2002/07/28 10:03:27 rmk Exp $
  *
  * A note about mapbase / membase
  *
@@ -25,29 +25,17 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/compiler.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/slab.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/serial_reg.h>
 #include <linux/serialP.h>
 #include <linux/delay.h>
-#include <linux/kmod.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
 
 #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -724,24 +712,18 @@
 static void serial8250_stop_rx(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
-	unsigned long flags;
 
-	spin_lock_irqsave(&up->port.lock, flags);
 	up->ier &= ~UART_IER_RLSI;
 	up->port.read_status_mask &= ~UART_LSR_DR;
 	serial_out(up, UART_IER, up->ier);
-	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static void serial8250_enable_ms(struct uart_port *port)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
-	unsigned long flags;
 
-	spin_lock_irqsave(&up->port.lock, flags);
 	up->ier |= UART_IER_MSI;
 	serial_out(up, UART_IER, up->ier);
-	spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static _INLINE_ void
@@ -1364,17 +1346,18 @@
 		up->port.ignore_status_mask |= UART_LSR_DR;
 
 	/*
+	 * Ok, we're now changing the port state.  Do it with
+	 * interrupts disabled.
+	 */
+	spin_lock_irqsave(&up->port.lock, flags);
+
+	/*
 	 * CTS flow control flag and modem status interrupts
 	 */
 	up->ier &= ~UART_IER_MSI;
 	if (UART_ENABLE_MS(&up->port, cflag))
 		up->ier |= UART_IER_MSI;
 
-	/*
-	 * Ok, we're now changing the port state.  Do it with
-	 * interrupts disabled.
-	 */
-	spin_lock_irqsave(&up->port.lock, flags);
 	serial_out(up, UART_IER, up->ier);
 
 	if (uart_config[up->port.type].flags & UART_STARTECH) {
@@ -1956,7 +1939,7 @@
 {
 	int ret, i;
 
-	printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.84 $ "
+	printk(KERN_INFO "Serial: 8250/16550 driver $Revision: 1.90 $ "
 		"IRQ sharing %sabled\n", share_irqs ? "en" : "dis");
 
 	for (i = 0; i < NR_IRQS; i++)
@@ -1988,7 +1971,7 @@
 EXPORT_SYMBOL(serial8250_get_irq_map);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.84 $");
+MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $");
 
 MODULE_PARM(share_irqs, "i");
 MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices"
diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
--- a/drivers/serial/8250_pci.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/serial/8250_pci.c	Thu Aug  1 14:17:41 2002
@@ -11,7 +11,7 @@
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License.
  *
- *  $Id: 8250_pci.c,v 1.19 2002/07/21 21:32:30 rmk Exp $
+ *  $Id: 8250_pci.c,v 1.24 2002/07/29 14:39:56 rmk Exp $
  */
 #include <linux/module.h>
 #include <linux/init.h>
@@ -30,6 +30,7 @@
 #include <asm/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/serial.h>
+#include <asm/io.h>
 
 #include "8250.h"
 
@@ -137,7 +138,29 @@
 			offset = 8 * (idx - 2);
 		}
 	}
-  
+
+	/* HP's Diva chip puts the 4th/5th serial port further out, and
+	 * some serial ports are supposed to be hidden on certain models.
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_HP &&
+	    dev->device == PCI_DEVICE_ID_HP_DIVA) {
+		switch (dev->subsystem_device) {
+		case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+			if (idx == 3)
+				idx++;
+			break;
+		case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+			if (idx > 0)
+				idx++;
+			if (idx > 2)
+				idx++;
+			break;
+		}
+		if (idx > 2) {
+			offset = 0x18;
+		}
+	}
+
 	port =  pci_resource_start(dev, base_idx) + offset;
 
 	if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
@@ -379,6 +402,41 @@
 	return 0;
 }
 
+/*
+ * HP's Remote Management Console.  The Diva chip came in several
+ * different versions.  N-class, L2000 and A500 have two Diva chips, each
+ * with 3 UARTs (the third UART on the second chip is unused).  Superdome
+ * and Keystone have one Diva chip with 3 UARTs.  Some later machines have
+ * one Diva chip, but it has been expanded to 5 UARTs.
+ */
+static int __devinit
+pci_hp_diva(struct pci_dev *dev, struct pci_board *board, int enable)
+{
+	if (!enable)
+		return 0;
+
+	switch (dev->subsystem_device) {
+	case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
+	case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
+	case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
+	case PCI_DEVICE_ID_HP_DIVA_EVEREST:
+		board->num_ports = 3;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
+		board->num_ports = 2;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
+		board->num_ports = 4;
+		break;
+	case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
+		board->num_ports = 1;
+		break;
+	}
+
+	return 0;
+}
+
+
 static int __devinit
 pci_xircom_fn(struct pci_dev *dev, struct pci_board *board, int enable)
 {
@@ -423,6 +481,7 @@
 	pbn_b1_4_1382400,
 	pbn_b1_8_1382400,
 
+	pbn_b2_1_115200,
 	pbn_b2_8_115200,
 	pbn_b2_4_460800,
 	pbn_b2_8_460800,
@@ -443,6 +502,7 @@
 	pbn_timedia,
 	pbn_intel_i960,
 	pbn_sgi_ioc3,
+	pbn_hp_diva,
 	pbn_nec_nile4,
 
 	pbn_dci_pccom4,
@@ -501,6 +561,7 @@
 	{ SPCI_FL_BASE1, 4, 1382400 },		/* pbn_b1_4_1382400 */
 	{ SPCI_FL_BASE1, 8, 1382400 },		/* pbn_b1_8_1382400 */
 
+	{ SPCI_FL_BASE2, 1, 115200 },		/* pbn_b2_1_115200 */
 	{ SPCI_FL_BASE2, 8, 115200 },		/* pbn_b2_8_115200 */
 	{ SPCI_FL_BASE2, 4, 460800 },		/* pbn_b2_4_460800 */
 	{ SPCI_FL_BASE2, 8, 460800 },		/* pbn_b2_8_460800 */
@@ -531,6 +592,7 @@
 		8<<2, 2, pci_inteli960ni_fn, 0x10000},
 	{ SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE,		   /* pbn_sgi_ioc3 */
 		1, 458333, 0, 0, 0, 0x20178 },
+	{ SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0 },/* pbn_hp_diva */
 
 	/*
 	 * NEC Vrc-5074 (Nile 4) builtin UART.
@@ -636,9 +698,10 @@
 		return rc;
 
 	if (ent->driver_data == pbn_default &&
-	    serial_pci_guess_board(dev, board))
+	    serial_pci_guess_board(dev, board)) {
+		pci_disable_device(dev);
 		return -ENODEV;
-	else if (serial_pci_guess_board(dev, &tmp) == 0) {
+	} else if (serial_pci_guess_board(dev, &tmp) == 0) {
 		printk(KERN_INFO "Redundant entry in serial pci_table.  "
 		       "Please send the output of\n"
 		       "lspci -vv, this message (%d,%d,%d,%d)\n"
@@ -652,8 +715,10 @@
 	priv = kmalloc(sizeof(struct serial_private) +
 			      sizeof(unsigned int) * board->num_ports,
 			      GFP_KERNEL);
-	if (!priv)
+	if (!priv) {
+		pci_disable_device(dev);
 		return -ENOMEM;
+	}
 
 	/*
 	 * Run the initialization function, if any
@@ -661,6 +726,7 @@
 	if (board->init_fn) {
 		rc = board->init_fn(dev, board, 1);
 		if (rc != 0) {
+			pci_disable_device(dev);
 			kfree(priv);
 			return rc;
 		}
@@ -1074,6 +1140,14 @@
 		0xFF00, 0, 0, 0,
 		pbn_sgi_ioc3 },
 
+	/* HP Diva card */
+	{	PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_hp_diva },
+	{	PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_b2_1_115200 },
+
 	/*
 	 * NEC Vrc-5074 (Nile 4) builtin UART.
 	 */
@@ -1102,14 +1176,6 @@
 		0xffff00, },
 	{ 0, }
 };
-
-#ifndef __devexit_p
-#if defined(MODULE) || defined(CONFIG_HOTPLUG)
-#define __devexit_p(x) x
-#else
-#define __devexit_p(x) NULL
-#endif
-#endif
 
 static struct pci_driver serial_pci_driver = {
 	.name		= "serial",
diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c
--- a/drivers/serial/amba.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/serial/amba.c	Thu Aug  1 14:17:36 2002
@@ -22,7 +22,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *  $Id: amba.c,v 1.37 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: amba.c,v 1.41 2002/07/28 10:03:27 rmk Exp $
  *
  * This is a generic driver for ARM AMBA-type serial ports.  They
  * have a lot of 16550-like features, but are not register compatable.
@@ -33,30 +33,15 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/circ_buf.h>
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
 
 #if defined(CONFIG_SERIAL_AMBA_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -138,26 +123,20 @@
 
 static void ambauart_stop_rx(struct uart_port *port)
 {
-	unsigned long flags;
 	unsigned int cr;
 
-	spin_lock_irqsave(&port->lock, flags);
 	cr = UART_GET_CR(port);
 	cr &= ~(AMBA_UARTCR_RIE | AMBA_UARTCR_RTIE);
 	UART_PUT_CR(port, cr);
-	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void ambauart_enable_ms(struct uart_port *port)
 {
-	unsigned long flags;
 	unsigned int cr;
 
-	spin_lock_irqsave(&port->lock, flags);
 	cr = UART_GET_CR(port);
 	cr |= AMBA_UARTCR_MSIE;
 	UART_PUT_CR(port, cr);
-	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void
@@ -742,7 +721,7 @@
 {
 	int ret;
 
-	printk(KERN_INFO "Serial: AMBA driver $Revision: 1.37 $\n");
+	printk(KERN_INFO "Serial: AMBA driver $Revision: 1.41 $\n");
 
 	ret = uart_register_driver(&amba_reg);
 	if (ret == 0) {
@@ -770,5 +749,5 @@
 EXPORT_NO_SYMBOLS;
 
 MODULE_AUTHOR("ARM Ltd/Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.37 $");
+MODULE_DESCRIPTION("ARM AMBA serial port driver $Revision: 1.41 $");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c
--- a/drivers/serial/anakin.c	Thu Aug  1 14:17:37 2002
+++ b/drivers/serial/anakin.c	Thu Aug  1 14:17:37 2002
@@ -19,35 +19,20 @@
  *   			SA_INTERRUPT. Works reliably now. No longer requires
  *   			changes to the serial_core API.
  *
- *  $Id: anakin.c,v 1.29 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: anakin.c,v 1.32 2002/07/28 10:03:27 rmk Exp $
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/circ_buf.h>
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
 
 #include <linux/serial_core.h>
 
@@ -119,13 +104,9 @@
 static void
 anakin_stop_rx(struct uart_port *port)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->lock, flags);
 	while (anakin_in(port, 0x10) & RXRELEASE) 
 	    anakin_in(port, 0x14);
 	anakin_out(port, 0x18, anakin_in(port, 0x18) | BLOCKRX);
-	spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static void
@@ -518,7 +499,7 @@
 {
 	int ret;
 
-	printk(KERN_INFO "Serial: Anakin driver $Revision: 1.29 $\n");
+	printk(KERN_INFO "Serial: Anakin driver $Revision: 1.32 $\n");
 
 	ret = uart_register_driver(&anakin_reg);
 	if (ret == 0) {
diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
--- a/drivers/serial/clps711x.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/serial/clps711x.c	Thu Aug  1 14:17:39 2002
@@ -22,37 +22,22 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *  $Id: clps711x.c,v 1.40 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: clps711x.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
  *
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/circ_buf.h>
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/spinlock.h>
 
-#include <asm/bitops.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
 
 #if defined(CONFIG_SERIAL_CLPS711X_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -597,7 +582,7 @@
 {
 	int ret, i;
 
-	printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.40 $\n");
+	printk(KERN_INFO "Serial: CLPS711x driver $Revision: 1.42 $\n");
 
 	ret = uart_register_driver(&clps711x_reg);
 	if (ret)
@@ -625,5 +610,5 @@
 EXPORT_NO_SYMBOLS;
 
 MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.40 $");
+MODULE_DESCRIPTION("CLPS-711x generic serial driver $Revision: 1.42 $");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c
--- a/drivers/serial/core.c	Thu Aug  1 14:17:39 2002
+++ b/drivers/serial/core.c	Thu Aug  1 14:17:39 2002
@@ -22,38 +22,22 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *  $Id: core.c,v 1.91 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: core.c,v 1.100 2002/07/28 10:03:28 rmk Exp $
  *
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/circ_buf.h>
 #include <linux/console.h>
-#include <linux/sysrq.h>
 #include <linux/pm.h>
 #include <linux/serial_core.h>
 #include <linux/smp_lock.h>
 #include <linux/serial.h> /* for serial_state and serial_icounter_struct */
 
-#include <asm/system.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
-#include <asm/bitops.h>
 
 #undef	DEBUG
 #ifdef DEBUG
@@ -931,12 +915,12 @@
 	 */
 	spin_lock_irq(&port->lock);
 	memcpy(&cprev, &port->icount, sizeof(struct uart_icount));
-	spin_unlock_irq(&port->lock);
 
 	/*
 	 * Force modem status interrupts on
 	 */
 	port->ops->enable_ms(port);
+	spin_unlock_irq(&port->lock);
 
 	add_wait_queue(&info->delta_msr_wait, &wait);
 	for (;;) {
@@ -1200,7 +1184,9 @@
 	 * disable the receive line status interrupts.
 	 */
 	if (info->flags & UIF_INITIALIZED) {
+		spin_lock_irqsave(&port->lock, flags);
 		port->ops->stop_rx(port);
+		spin_unlock_irqrestore(&port->lock, flags);
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
@@ -1948,8 +1934,8 @@
 			spin_lock_irq(&port->lock);
 			ops->stop_tx(port, 0);
 			ops->set_mctrl(port, 0);
-			spin_unlock_irq(&port->lock);
 			ops->stop_rx(port);
+			spin_unlock_irq(&port->lock);
 			ops->shutdown(port);
 		}
 		if (ops->pm)
diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
--- a/drivers/serial/sa1100.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/serial/sa1100.c	Thu Aug  1 14:17:36 2002
@@ -21,35 +21,20 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *  $Id: sa1100.c,v 1.43 2002/07/22 15:27:32 rmk Exp $
+ *  $Id: sa1100.c,v 1.50 2002/07/29 14:41:04 rmk Exp $
  *
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/circ_buf.h>
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
 #include <asm/hardware.h>
 #include <asm/mach/serial_sa1100.h>
 
@@ -190,13 +175,10 @@
 static void sa1100_stop_rx(struct uart_port *port)
 {
 	struct sa1100_port *sport = (struct sa1100_port *)port;
-	unsigned long flags;
 	u32 utcr3;
 
-	spin_lock_irqsave(&sport->port.lock, flags);
 	utcr3 = UART_GET_UTCR3(sport);
 	UART_PUT_UTCR3(sport, utcr3 & ~UTCR3_RIE);
-	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 /*
@@ -426,7 +408,9 @@
 	/*
 	 * Enable modem status interrupts
 	 */
+	spin_lock_irq(&sport->port.lock);
 	sa1100_enable_ms(&sport->port);
+	spin_unlock_irq(&sport->port.lock);
 
 	return 0;
 }
@@ -527,10 +511,11 @@
 	UART_PUT_UTSR0(sport, -1);
 
 	UART_PUT_UTCR3(sport, old_utcr3);
-	spin_unlock_irqrestore(&sport->port.lock, flags);
 
 	if (UART_ENABLE_MS(&sport->port, cflag))
 		sa1100_enable_ms(&sport->port);
+
+	spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 static const char *sa1100_type(struct uart_port *port)
@@ -857,7 +842,7 @@
 {
 	int ret;
 
-	printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.43 $\n");
+	printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n");
 
 	sa1100_init_ports();
 	ret = uart_register_driver(&sa1100_reg);
@@ -886,5 +871,5 @@
 EXPORT_NO_SYMBOLS;
 
 MODULE_AUTHOR("Deep Blue Solutions Ltd");
-MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.43 $");
+MODULE_DESCRIPTION("SA1100 generic serial port driver $Revision: 1.50 $");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c
--- a/drivers/serial/uart00.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/serial/uart00.c	Thu Aug  1 14:17:40 2002
@@ -21,36 +21,21 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- *  $Id: uart00.c,v 1.33 2002/07/21 21:32:31 rmk Exp $
+ *  $Id: uart00.c,v 1.35 2002/07/28 10:03:28 rmk Exp $
  *
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
 #include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/circ_buf.h>
 #include <linux/serial.h>
 #include <linux/console.h>
 #include <linux/sysrq.h>
 #include <linux/pld/pld_hotswap.h>
 
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
 #include <asm/sizes.h>
 
 #if defined(CONFIG_SERIAL_UART00_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
@@ -755,7 +740,7 @@
 {
 	int result;
 
-	printk(KERN_INFO "Serial: UART00 driver $Revision: 1.33 $\n");
+	printk(KERN_INFO "Serial: UART00 driver $Revision: 1.35 $\n");
 
 	printk(KERN_WARNING "serial_uart00:Using temporary major/minor pairs"
 		" - these WILL change in the future\n");
diff -Nru a/drivers/sgi/char/Makefile b/drivers/sgi/char/Makefile
--- a/drivers/sgi/char/Makefile	Thu Aug  1 14:17:36 2002
+++ b/drivers/sgi/char/Makefile	Thu Aug  1 14:17:36 2002
@@ -2,7 +2,7 @@
 # Makefile for the linux kernel.
 #
 
-export-objs	:= newport.o shmiq.o sgicons.o usema.o
+export-objs	:= newport.o shmiq.o sgicons.o usema.o rrm.o
 obj-y		:= newport.o shmiq.o sgicons.o usema.o streamable.o
 
 obj-$(CONFIG_SGI_SERIAL)	+= sgiserial.o
diff -Nru a/drivers/sgi/char/shmiq.c b/drivers/sgi/char/shmiq.c
--- a/drivers/sgi/char/shmiq.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/sgi/char/shmiq.c	Thu Aug  1 14:17:41 2002
@@ -466,7 +466,7 @@
 shmiq_init (void)
 {
 	printk ("SHMIQ setup\n");
-	devfs_register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops);
+	register_chrdev(SHMIQ_MAJOR, "shmiq", &shmiq_fops);
 	devfs_register (NULL, "shmiq", DEVFS_FL_DEFAULT,
 			SHMIQ_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,
 			&shmiq_fops, NULL);
diff -Nru a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile
--- a/drivers/usb/core/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/usb/core/Makefile	Thu Aug  1 14:17:41 2002
@@ -2,7 +2,7 @@
 # Makefile for USB Core files and filesystem
 #
 
-export-objs	:= usb.o hcd.o hcd-pci.o urb.o message.o config.o file.o
+export-objs	:= usb.o hcd.o hcd-pci.o urb.o message.o file.o
 
 usbcore-objs	:= usb.o usb-debug.o hub.o hcd.o urb.o message.o \
 			config.o file.o
diff -Nru a/drivers/usb/core/file.c b/drivers/usb/core/file.c
--- a/drivers/usb/core/file.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/usb/core/file.c	Thu Aug  1 14:17:41 2002
@@ -71,7 +71,7 @@
 
 int usb_major_init(void)
 {
-	if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
+	if (register_chrdev(USB_MAJOR, "usb", &usb_fops)) {
 		err("unable to get major %d for usb devices", USB_MAJOR);
 		return -EBUSY;
 	}
@@ -84,7 +84,7 @@
 void usb_major_cleanup(void)
 {
 	devfs_unregister(usb_devfs_handle);
-	devfs_unregister_chrdev(USB_MAJOR, "usb");
+	unregister_chrdev(USB_MAJOR, "usb");
 }
 
 /**
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/usb/core/hub.c	Thu Aug  1 14:17:40 2002
@@ -1059,9 +1059,9 @@
 	/* Send me a signal to get me die (for debugging) */
 	do {
 		usb_hub_events();
+		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); 
 		if (current->flags & PF_FREEZE)
 			refrigerator(PF_IOTHREAD);
-		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); 
 	} while (!signal_pending(current));
 
 	dbg("usb_hub_thread exiting");
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/usb/core/usb.c	Thu Aug  1 14:17:40 2002
@@ -835,11 +835,8 @@
 	udev = to_usb_device (dev);
 	return sprintf (buf, "%u\n", udev->actconfig->bConfigurationValue);
 }
-static struct driver_file_entry usb_config_entry = {
-	.name =	"configuration",
-	.mode =	S_IRUGO,
-	.show =	show_config,
-};
+
+static DEVICE_ATTR(config,"configuration",S_IRUGO,show_config,NULL);
 
 /* interfaces have one current setting; alternates
  * can have different endpoints and class info.
@@ -854,11 +851,7 @@
 	interface = to_usb_interface (dev);
 	return sprintf (buf, "%u\n", interface->altsetting->bAlternateSetting);
 }
-static struct driver_file_entry usb_altsetting_entry = {
-	.name =	"altsetting",
-	.mode =	S_IRUGO,
-	.show =	show_altsetting,
-};
+static DEVICE_ATTR(altsetting,"altsetting",S_IRUGO,show_altsetting,NULL);
 
 /* product driverfs file */
 static ssize_t show_product (struct device *dev, char *buf, size_t count, loff_t off)
@@ -875,11 +868,7 @@
 	buf[len+1] = 0x00;
 	return len+1;
 }
-static struct driver_file_entry usb_product_entry = {
-	.name =	"product",
-	.mode =	S_IRUGO,
-	.show =	show_product,
-};
+static DEVICE_ATTR(product,"product",S_IRUGO,show_product,NULL);
 
 /* manufacturer driverfs file */
 static ssize_t
@@ -897,11 +886,7 @@
 	buf[len+1] = 0x00;
 	return len+1;
 }
-static struct driver_file_entry usb_manufacturer_entry = {
-	.name =	"manufacturer",
-	.mode =	S_IRUGO,
-	.show =	show_manufacturer,
-};
+static DEVICE_ATTR(manufacturer,"manufacturer",S_IRUGO,show_manufacturer,NULL);
 
 /* serial number driverfs file */
 static ssize_t
@@ -919,11 +904,7 @@
 	buf[len+1] = 0x00;
 	return len+1;
 }
-static struct driver_file_entry usb_serial_entry = {
-	.name =	"serial",
-	.mode =	S_IRUGO,
-	.show =	show_serial,
-};
+static DEVICE_ATTR(serial,"serial",S_IRUGO,show_serial,NULL);
 
 /*
  * This entrypoint gets called for each new device.
@@ -965,7 +946,7 @@
 				interface->altsetting->bInterfaceNumber);
 		}
 		device_register (&interface->dev);
-		device_create_file (&interface->dev, &usb_altsetting_entry);
+		device_create_file (&interface->dev, &dev_attr_altsetting);
 
 		/* if this interface hasn't already been claimed */
 		if (!usb_interface_claimed(interface)) {
@@ -1453,13 +1434,13 @@
 	err = device_register (&dev->dev);
 	if (err)
 		return err;
-	device_create_file (&dev->dev, &usb_config_entry);
+	device_create_file (&dev->dev, &dev_attr_config);
 	if (dev->descriptor.iManufacturer)
-		device_create_file (&dev->dev, &usb_manufacturer_entry);
+		device_create_file (&dev->dev, &dev_attr_manufacturer);
 	if (dev->descriptor.iProduct)
-		device_create_file (&dev->dev, &usb_product_entry);
+		device_create_file (&dev->dev, &dev_attr_product);
 	if (dev->descriptor.iSerialNumber)
-		device_create_file (&dev->dev, &usb_serial_entry);
+		device_create_file (&dev->dev, &dev_attr_serial);
 
 	/* now that the basic setup is over, add a /proc/bus/usb entry */
 	usbfs_add_device(dev);
diff -Nru a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
--- a/drivers/usb/host/Makefile	Thu Aug  1 14:17:41 2002
+++ b/drivers/usb/host/Makefile	Thu Aug  1 14:17:41 2002
@@ -3,8 +3,6 @@
 # framework and drivers
 #
 
-export-objs := usb-ohci.o
-
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_OHCI_HCD)	+= ohci-hcd.o
 obj-$(CONFIG_USB_UHCI_HCD_ALT)	+= uhci-hcd.o
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/usb/host/ohci-q.c	Thu Aug  1 14:17:41 2002
@@ -534,6 +534,8 @@
 	/* aim for only one interrupt per urb.  mostly applies to control
 	 * and iso; other urbs rarely need more than one TD per urb.
 	 * this way, only final tds (or ones with an error) cause IRQs.
+	 * at least immediately; use DI=6 in case any control request is
+	 * tempted to die part way through.
 	 *
 	 * NOTE: could delay interrupts even for the last TD, and get fewer
 	 * interrupts ... increasing per-urb latency by sharing interrupts.
@@ -541,7 +543,7 @@
 	 */
 	if (index != (urb_priv->length - 1)
 			|| (urb->transfer_flags & URB_NO_INTERRUPT))
-		info |= TD_DI_SET (7);
+		info |= TD_DI_SET (6);
 
 	/* use this td as the next dummy */
 	td_pt = urb_priv->td [index];
@@ -809,12 +811,16 @@
 	ohci->hcca->done_head = 0;
 
 	while (td_list_hc) {		
+	    	int		cc;
+
 		td_list = dma_to_td (ohci, td_list_hc);
 
 		td_list->hwINFO |= cpu_to_le32 (TD_DONE);
 
-		if (TD_CC_GET (le32_to_cpup (&td_list->hwINFO))) {
+		cc = TD_CC_GET (le32_to_cpup (&td_list->hwINFO));
+		if (cc != TD_CC_NOERROR) {
 			urb_priv = (urb_priv_t *) td_list->urb->hcpriv;
+
 			/* Non-iso endpoints can halt on error; un-halt,
 			 * and dequeue any other TDs from this urb.
 			 * No other TD could have caused the halt.
@@ -822,12 +828,21 @@
 			if (td_list->ed->hwHeadP & ED_H) {
 				if (urb_priv && ((td_list->index + 1)
 						< urb_priv->length)) {
-#ifdef OHCI_VERBOSE_DEBUG
-					dbg ("urb %p TD %p (%d/%d), patch ED",
-						td_list->urb, td_list,
+					struct urb *urb = td_list->urb;
+
+					/* help for troubleshooting: */
+					dbg ("urb %p usb-%s-%s ep-%d-%s "
+						    "(td %d/%d), "
+						    "cc %d --> status %d",
+						td_list->urb,
+						urb->dev->bus->bus_name,
+						urb->dev->devpath,
+						usb_pipeendpoint (urb->pipe),
+						usb_pipein (urb->pipe)
+						    ? "IN" : "OUT",
 						1 + td_list->index,
-						urb_priv->length);
-#endif
+						urb_priv->length,
+						cc, cc_to_error [cc]);
 					td_list->ed->hwHeadP = 
 			    (urb_priv->td [urb_priv->length - 1]->hwNextTD
 				    & __constant_cpu_to_le32 (TD_MASK))
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/usb/input/hiddev.c	Thu Aug  1 14:17:40 2002
@@ -765,8 +765,11 @@
 
 int __init hiddev_init(void)
 {
-	hiddev_devfs_handle =
-		devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL);
+	devfs_handle_t de;
+
+	de = devfs_get_handle(NULL, "usb", 0, 0, 0, 0);
+	hiddev_devfs_handle = devfs_mk_dir(de, "hid", NULL);
+	devfs_put(de);
 	usb_register(&hiddev_driver);
 	return 0;
 }
diff -Nru a/drivers/usb/misc/tiglusb.c b/drivers/usb/misc/tiglusb.c
--- a/drivers/usb/misc/tiglusb.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/usb/misc/tiglusb.c	Thu Aug  1 14:17:36 2002
@@ -476,7 +476,7 @@
 	}
 
 	/* register device */
-	if (devfs_register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
+	if (register_chrdev (TIUSB_MAJOR, "tiglusb", &tiglusb_fops)) {
 		err ("unable to get major %d", TIUSB_MAJOR);
 		return -EIO;
 	}
@@ -487,7 +487,7 @@
 	/* register USB module */
 	result = usb_register (&tiglusb_driver);
 	if (result < 0) {
-		devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb");
+		unregister_chrdev (TIUSB_MAJOR, "tiglusb");
 		return -1;
 	}
 
@@ -501,7 +501,7 @@
 {
 	usb_deregister (&tiglusb_driver);
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev (TIUSB_MAJOR, "tiglusb");
+	unregister_chrdev (TIUSB_MAJOR, "tiglusb");
 }
 
 /* --------------------------------------------------------------------- */
diff -Nru a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
--- a/drivers/usb/storage/freecom.c	Thu Aug  1 14:17:41 2002
+++ b/drivers/usb/storage/freecom.c	Thu Aug  1 14:17:41 2002
@@ -40,43 +40,47 @@
 static void pdump (void *, int);
 #endif
 
+/* Bits of HD_STATUS */
+#define ERR_STAT		0x01
+#define DRQ_STAT		0x08
+
 struct freecom_udata {
-        __u8    buffer[64];             /* Common command block. */
+        u8    buffer[64];             /* Common command block. */
 };
 typedef struct freecom_udata *freecom_udata_t;
 
 /* All of the outgoing packets are 64 bytes long. */
 struct freecom_cb_wrap {
-        __u8    Type;                   /* Command type. */
-        __u8    Timeout;                /* Timeout in seconds. */
-        __u8    Atapi[12];              /* An ATAPI packet. */
-        __u8    Filler[50];             /* Padding Data. */
+        u8    Type;                   /* Command type. */
+        u8    Timeout;                /* Timeout in seconds. */
+        u8    Atapi[12];              /* An ATAPI packet. */
+        u8    Filler[50];             /* Padding Data. */
 };
 
 struct freecom_xfer_wrap {
-        __u8    Type;                   /* Command type. */
-        __u8    Timeout;                /* Timeout in seconds. */
-        __u32   Count;                  /* Number of bytes to transfer. */
-        __u8    Pad[58];
+        u8    Type;                   /* Command type. */
+        u8    Timeout;                /* Timeout in seconds. */
+        u32   Count;                  /* Number of bytes to transfer. */
+        u8    Pad[58];
 } __attribute__ ((packed));
 
 struct freecom_ide_out {
-        __u8    Type;                   /* Type + IDE register. */
-        __u8    Pad;
-        __u16   Value;                  /* Value to write. */
-        __u8    Pad2[60];
+        u8    Type;                   /* Type + IDE register. */
+        u8    Pad;
+        u16   Value;                  /* Value to write. */
+        u8    Pad2[60];
 };
 
 struct freecom_ide_in {
-        __u8    Type;                   /* Type | IDE register. */
-        __u8    Pad[63];
+        u8    Type;                   /* Type | IDE register. */
+        u8    Pad[63];
 };
 
 struct freecom_status {
-        __u8    Status;
-        __u8    Reason;
-        __u16   Count;
-        __u8    Pad[60];
+        u8    Status;
+        u8    Reason;
+        u16   Count;
+        u8    Pad[60];
 };
 
 /* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
diff -Nru a/drivers/video/aty/Makefile b/drivers/video/aty/Makefile
--- a/drivers/video/aty/Makefile	Thu Aug  1 14:17:39 2002
+++ b/drivers/video/aty/Makefile	Thu Aug  1 14:17:39 2002
@@ -1,6 +1,3 @@
-
-export-objs    :=  atyfb_base.o mach64_accel.o
-
 obj-$(CONFIG_FB_ATY) += atyfb.o
 
 atyfb-y				:= atyfb_base.o mach64_accel.o ../cfbimgblt.o
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	Thu Aug  1 14:17:36 2002
+++ b/drivers/video/fbmem.c	Thu Aug  1 14:17:36 2002
@@ -845,7 +845,7 @@
 	create_proc_read_entry("fb", 0, 0, fbmem_read_proc, NULL);
 
 	devfs_handle = devfs_mk_dir (NULL, "fb", NULL);
-	if (devfs_register_chrdev(FB_MAJOR,"fb",&fb_fops))
+	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
 		printk("unable to get major %d for fb devs\n", FB_MAJOR);
 
 #ifdef CONFIG_FB_OF
diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c
--- a/drivers/video/modedb.c	Thu Aug  1 14:17:40 2002
+++ b/drivers/video/modedb.c	Thu Aug  1 14:17:40 2002
@@ -111,10 +111,6 @@
 	NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12,
 	0, FB_VMODE_INTERLACED
     }, {
-	/* 1400x1050 @ 60Hz, 63.9 kHz hsync */
-	NULL, 68, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3,
-	0, FB_VMODE_NONINTERLACED
-    }, {
 	/* 800x600 @ 100 Hz, 64.02 kHz hsync */
 	NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6,
 	0, FB_VMODE_NONINTERLACED
diff -Nru a/fs/Config.in b/fs/Config.in
--- a/fs/Config.in	Thu Aug  1 14:17:41 2002
+++ b/fs/Config.in	Thu Aug  1 14:17:41 2002
@@ -26,7 +26,7 @@
 
 dep_tristate 'BFS file system support (EXPERIMENTAL)' CONFIG_BFS_FS $CONFIG_EXPERIMENTAL
 
-tristate 'Ext3 journalling file system support (EXPERIMENTAL)' CONFIG_EXT3_FS
+tristate 'Ext3 journalling file system support' CONFIG_EXT3_FS
 # CONFIG_JBD could be its own option (even modular), but until there are
 # other users than ext3, we will simply make it be the same as CONFIG_EXT3_FS
 # dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
diff -Nru a/fs/Makefile b/fs/Makefile
--- a/fs/Makefile	Thu Aug  1 14:17:36 2002
+++ b/fs/Makefile	Thu Aug  1 14:17:36 2002
@@ -7,8 +7,7 @@
 
 O_TARGET := fs.o
 
-export-objs :=	filesystems.o open.o dcache.o buffer.o bio.o inode.o dquot.o \
-		mpage.o
+export-objs :=	open.o dcache.o buffer.o bio.o inode.o dquot.o mpage.o
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
 		bio.o super.o block_dev.o char_dev.o stat.o exec.o pipe.o \
diff -Nru a/fs/adfs/file.c b/fs/adfs/file.c
--- a/fs/adfs/file.c	Thu Aug  1 14:17:37 2002
+++ b/fs/adfs/file.c	Thu Aug  1 14:17:37 2002
@@ -36,6 +36,7 @@
 	mmap:		generic_file_mmap,
 	fsync:		file_fsync,
 	write:		generic_file_write,
+	sendfile:	generic_file_sendfile,
 };
 
 struct inode_operations adfs_file_inode_operations = {
diff -Nru a/fs/affs/file.c b/fs/affs/file.c
--- a/fs/affs/file.c	Thu Aug  1 14:17:40 2002
+++ b/fs/affs/file.c	Thu Aug  1 14:17:40 2002
@@ -50,6 +50,7 @@
 	open:		affs_file_open,
 	release:	affs_file_release,
 	fsync:		file_fsync,
+	sendfile:	generic_file_sendfile,
 };
 
 struct inode_operations affs_file_inode_operations = {
diff -Nru a/fs/bfs/file.c b/fs/bfs/file.c
--- a/fs/bfs/file.c	Thu Aug  1 14:17:36 2002
+++ b/fs/bfs/file.c	Thu Aug  1 14:17:36 2002
@@ -18,10 +18,11 @@
 #endif
 
 struct file_operations bfs_file_operations = {
-	llseek: generic_file_llseek,
-	read:	generic_file_read,
-	write:	generic_file_write,
-	mmap:	generic_file_mmap,
+	llseek: 	generic_file_llseek,
+	read:		generic_file_read,
+	write:		generic_file_write,
+	mmap:		generic_file_mmap,
+	sendfile:	generic_file_sendfile,
 };
 
 static int bfs_move_block(unsigned long from, unsigned long to, struct super_block *sb)
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	Thu Aug  1 14:17:40 2002
+++ b/fs/binfmt_elf.c	Thu Aug  1 14:17:40 2002
@@ -33,6 +33,7 @@
 #include <linux/smp_lock.h>
 #include <linux/compiler.h>
 #include <linux/highmem.h>
+#include <linux/pagemap.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -1249,7 +1250,7 @@
 					flush_page_to_ram(page);
 					kunmap(page);
 				}
-				put_page(page);
+				page_cache_release(page);
 			}
 		}
 	}
diff -Nru a/fs/block_dev.c b/fs/block_dev.c
--- a/fs/block_dev.c	Thu Aug  1 14:17:41 2002
+++ b/fs/block_dev.c	Thu Aug  1 14:17:41 2002
@@ -24,14 +24,14 @@
 
 #include <asm/uaccess.h>
 
-static unsigned long max_block(struct block_device *bdev)
+static sector_t max_block(struct block_device *bdev)
 {
-	unsigned int retval = ~0U;
+	sector_t retval = ~0U;
 	loff_t sz = bdev->bd_inode->i_size;
 
 	if (sz) {
-		unsigned int size = block_size(bdev);
-		unsigned int sizebits = blksize_bits(size);
+		sector_t size = block_size(bdev);
+		unsigned sizebits = blksize_bits(size);
 		retval = (sz >> sizebits);
 	}
 	return retval;
@@ -88,7 +88,9 @@
 	return sb_set_blocksize(sb, size);
 }
 
-static int blkdev_get_block(struct inode * inode, sector_t iblock, struct buffer_head * bh, int create)
+static int
+blkdev_get_block(struct inode *inode, sector_t iblock,
+		struct buffer_head *bh, int create)
 {
 	if (iblock >= max_block(inode->i_bdev))
 		return -EIO;
@@ -100,11 +102,25 @@
 }
 
 static int
+blkdev_get_blocks(struct inode *inode, sector_t iblock,
+		unsigned long max_blocks, struct buffer_head *bh, int create)
+{
+	if ((iblock + max_blocks) >= max_block(inode->i_bdev))
+		return -EIO;
+
+	bh->b_bdev = inode->i_bdev;
+	bh->b_blocknr = iblock;
+	bh->b_size = max_blocks << inode->i_blkbits;
+	set_buffer_mapped(bh);
+	return 0;
+}
+
+static int
 blkdev_direct_IO(int rw, struct inode *inode, char *buf,
 			loff_t offset, size_t count)
 {
 	return generic_direct_IO(rw, inode, buf, offset,
-				count, blkdev_get_block);
+				count, blkdev_get_blocks);
 }
 
 static int blkdev_writepage(struct page * page)
@@ -437,6 +453,8 @@
 
 int register_blkdev(unsigned int major, const char * name, struct block_device_operations *bdops)
 {
+	if (devfs_only())
+		return 0;
 	if (major == 0) {
 		for (major = MAX_BLKDEV-1; major > 0; major--) {
 			if (blkdevs[major].bdops == NULL) {
@@ -458,6 +476,8 @@
 
 int unregister_blkdev(unsigned int major, const char * name)
 {
+	if (devfs_only())
+		return 0;
 	if (major >= MAX_BLKDEV)
 		return -EINVAL;
 	if (!blkdevs[major].bdops)
@@ -489,11 +509,12 @@
 	if (bdops == NULL) {
 		devfs_handle_t de;
 
-		de = devfs_find_handle (NULL, NULL, i, minor(dev),
-					DEVFS_SPECIAL_BLK, 0);
+		de = devfs_get_handle(NULL, NULL, i, minor(dev),
+				      DEVFS_SPECIAL_BLK, 0);
 		if (de) {
-			bdops = devfs_get_ops (de);
-			devfs_put_ops (de); /* We're running in owner module */
+			bdops = devfs_get_ops(de);
+			devfs_put_ops(de); /* We're running in owner module */
+			devfs_put(de);
 		}
 	}
 	if (bdops == NULL)
@@ -578,9 +599,10 @@
 
 		bdev->bd_offset = 0;
 		if (g) {
-			bdev->bd_inode->i_size =
-				(loff_t) g->part[minor(dev)].nr_sects << 9;
-			bdev->bd_offset = g->part[minor(dev)].start_sect;
+			struct hd_struct *p;
+			p = g->part + minor(dev) - g->first_minor;
+			bdev->bd_inode->i_size = (loff_t) p->nr_sects << 9;
+			bdev->bd_offset = p->start_sect;
 		} else if (blk_size[major(dev)])
 			bdev->bd_inode->i_size =
 				(loff_t) blk_size[major(dev)][minor(dev)] << 10;
@@ -774,6 +796,7 @@
 	mmap:		generic_file_mmap,
 	fsync:		block_fsync,
 	ioctl:		blkdev_ioctl,
+	sendfile:	generic_file_sendfile,
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	Thu Aug  1 14:17:36 2002
+++ b/fs/buffer.c	Thu Aug  1 14:17:36 2002
@@ -448,9 +448,7 @@
 	 * We really want to use invalidate_inode_pages2() for
 	 * that, but not until that's cleaned up.
 	 */
-	current->flags |= PF_INVALIDATE;
 	invalidate_inode_pages(bdev->bd_inode);
-	current->flags &= ~PF_INVALIDATE;
 }
 
 void __invalidate_buffers(kdev_t dev, int destroy_dirty_buffers)
@@ -514,9 +512,8 @@
 		if (!buffer_uptodate(tmp))
 			page_uptodate = 0;
 		if (buffer_async_read(tmp)) {
-			if (buffer_locked(tmp))
-				goto still_busy;
-			BUG();
+			BUG_ON(!buffer_locked(tmp));
+			goto still_busy;
 		}
 		tmp = tmp->b_this_page;
 	} while (tmp != bh);
@@ -564,9 +561,8 @@
 	tmp = bh->b_this_page;
 	while (tmp != bh) {
 		if (buffer_async_write(tmp)) {
-			if (buffer_locked(tmp))
-				goto still_busy;
-			BUG();
+			BUG_ON(!buffer_locked(tmp));
+			goto still_busy;
 		}
 		tmp = tmp->b_this_page;
 	}
diff -Nru a/fs/coda/psdev.c b/fs/coda/psdev.c
--- a/fs/coda/psdev.c	Thu Aug  1 14:17:41 2002
+++ b/fs/coda/psdev.c	Thu Aug  1 14:17:41 2002
@@ -366,7 +366,7 @@
 
 static int init_coda_psdev(void)
 {
-	if(devfs_register_chrdev(CODA_PSDEV_MAJOR,"coda_psdev",
+	if(register_chrdev(CODA_PSDEV_MAJOR,"coda_psdev",
 				 &coda_psdev_fops)) {
               printk(KERN_ERR "coda_psdev: unable to get major %d\n", 
 		     CODA_PSDEV_MAJOR);
@@ -411,7 +411,7 @@
 	return 0;
 out:
 	devfs_unregister(devfs_handle);
-	devfs_unregister_chrdev(CODA_PSDEV_MAJOR,"coda_psdev");
+	unregister_chrdev(CODA_PSDEV_MAJOR,"coda_psdev");
 	coda_sysctl_clean();
 out1:
 	coda_destroy_inodecache();
@@ -428,7 +428,7 @@
                 printk("coda: failed to unregister filesystem\n");
         }
 	devfs_unregister(devfs_handle);
-	devfs_unregister_chrdev(CODA_PSDEV_MAJOR, "coda_psdev");
+	unregister_chrdev(CODA_PSDEV_MAJOR, "coda_psdev");
 	coda_sysctl_clean();
 	coda_destroy_inodecache();
 }
diff -Nru a/fs/coda/sysctl.c b/fs/coda/sysctl.c
--- a/fs/coda/sysctl.c	Thu Aug  1 14:17:40 2002
+++ b/fs/coda/sysctl.c	Thu Aug  1 14:17:40 2002
@@ -15,7 +15,6 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
-#include <linux/swapctl.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
diff -Nru a/fs/devfs/base.c b/fs/devfs/base.c
--- a/fs/devfs/base.c	Thu Aug  1 14:17:36 2002
+++ b/fs/devfs/base.c	Thu Aug  1 14:17:36 2002
@@ -639,6 +639,12 @@
     20020722   Richard Gooch <rgooch@atnf.csiro.au>
 	       Fixed devfs entry leak in <devfs_readdir> when *readdir fails.
   v1.18
+    20020725   Richard Gooch <rgooch@atnf.csiro.au>
+	       Created <devfs_find_and_unregister>.
+  v1.19
+    20020728   Richard Gooch <rgooch@atnf.csiro.au>
+	       Removed deprecated <devfs_find_handle>.
+  v1.20
 */
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -671,7 +677,7 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-#define DEVFS_VERSION            "1.18 (20020722)"
+#define DEVFS_VERSION            "1.20 (20020728)"
 
 #define DEVFS_NAME "devfs"
 
@@ -1881,19 +1887,15 @@
     return _devfs_find_entry (dir, name, major, minor, type,traverse_symlinks);
 }   /*  End Function devfs_get_handle  */
 
-
-/*  Compatibility function. Will be removed in sometime in 2.5  */
-
-devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name,
-				  unsigned int major, unsigned int minor,
-				  char type, int traverse_symlinks)
-{
-    devfs_handle_t de;
-
-    de = devfs_get_handle (dir, name, major, minor, type, traverse_symlinks);
+void devfs_find_and_unregister (devfs_handle_t dir, const char *name,
+				unsigned int major, unsigned int minor,
+				char type, int traverse_symlinks)
+{
+    devfs_handle_t de = devfs_get_handle (dir, name, major, minor,
+					  type, traverse_symlinks);
+    devfs_unregister (de);
     devfs_put (de);
-    return de;
-}   /*  End Function devfs_find_handle  */
+}
 
 
 /**
@@ -2226,75 +2228,17 @@
 
 
 /**
- *	devfs_register_chrdev - Optionally register a conventional character driver.
- *	@major: The major number for the driver.
- *	@name: The name of the driver (as seen in /proc/devices).
- *	@fops: The &file_operations structure pointer.
- *
- *	This function will register a character driver provided the "devfs=only"
- *	option was not provided at boot time.
- *	Returns 0 on success, else a negative error code on failure.
- */
-
-int devfs_register_chrdev (unsigned int major, const char *name,
-			   struct file_operations *fops)
-{
-    if (boot_options & OPTION_ONLY) return 0;
-    return register_chrdev (major, name, fops);
-}   /*  End Function devfs_register_chrdev  */
-
-
-/**
- *	devfs_register_blkdev - Optionally register a conventional block driver.
- *	@major: The major number for the driver.
- *	@name: The name of the driver (as seen in /proc/devices).
- *	@bdops: The &block_device_operations structure pointer.
- *
- *	This function will register a block driver provided the "devfs=only"
- *	option was not provided at boot time.
- *	Returns 0 on success, else a negative error code on failure.
- */
-
-int devfs_register_blkdev (unsigned int major, const char *name,
-			   struct block_device_operations *bdops)
-{
-    if (boot_options & OPTION_ONLY) return 0;
-    return register_blkdev (major, name, bdops);
-}   /*  End Function devfs_register_blkdev  */
-
-
-/**
- *	devfs_unregister_chrdev - Optionally unregister a conventional character driver.
- *	@major: The major number for the driver.
- *	@name: The name of the driver (as seen in /proc/devices).
+ *	devfs_only - returns if "devfs=only" is a boot option
  *
- *	This function will unregister a character driver provided the "devfs=only"
- *	option was not provided at boot time.
- *	Returns 0 on success, else a negative error code on failure.
+ *	If "devfs=only" this function will return 1, otherwise 0 is returned.
  */
-
-int devfs_unregister_chrdev (unsigned int major, const char *name)
+int devfs_only (void)
 {
-    if (boot_options & OPTION_ONLY) return 0;
-    return unregister_chrdev (major, name);
-}   /*  End Function devfs_unregister_chrdev  */
-
-
-/**
- *	devfs_unregister_blkdev - Optionally unregister a conventional block driver.
- *	@major: The major number for the driver.
- *	@name: The name of the driver (as seen in /proc/devices).
- *
- *	This function will unregister a block driver provided the "devfs=only"
- *	option was not provided at boot time.
- *	Returns 0 on success, else a negative error code on failure.
- */
+    if (boot_options & OPTION_ONLY)
+	    return 1;
+    return 0;
+}
 
-int devfs_unregister_blkdev (unsigned int major, const char *name)
-{
-    if (boot_options & OPTION_ONLY) return 0;
-    return unregister_blkdev (major, name);
-}   /*  End Function devfs_unregister_blkdev  */
 
 /**
  *	devfs_setup - Process kernel boot options.
@@ -2368,7 +2312,6 @@
 EXPORT_SYMBOL(devfs_mk_symlink);
 EXPORT_SYMBOL(devfs_mk_dir);
 EXPORT_SYMBOL(devfs_get_handle);
-EXPORT_SYMBOL(devfs_find_handle);
 EXPORT_SYMBOL(devfs_get_flags);
 EXPORT_SYMBOL(devfs_set_flags);
 EXPORT_SYMBOL(devfs_get_maj_min);
@@ -2384,10 +2327,6 @@
 EXPORT_SYMBOL(devfs_auto_unregister);
 EXPORT_SYMBOL(devfs_get_unregister_slave);
 EXPORT_SYMBOL(devfs_get_name);
-EXPORT_SYMBOL(devfs_register_chrdev);
-EXPORT_SYMBOL(devfs_register_blkdev);
-EXPORT_SYMBOL(devfs_unregister_chrdev);
-EXPORT_SYMBOL(devfs_unregister_blkdev);
 
 
 /**
diff -Nru a/fs/devices.c b/fs/devices.c
--- a/fs/devices.c	Thu Aug  1 14:17:40 2002
+++ b/fs/devices.c	Thu Aug  1 14:17:40 2002
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
+#include <linux/devfs_fs_kernel.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 
@@ -97,6 +98,8 @@
 
 int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
 {
+	if (devfs_only())
+		return 0;
 	if (major == 0) {
 		write_lock(&chrdevs_lock);
 		for (major = MAX_CHRDEV-1; major > 0; major--) {
@@ -125,6 +128,8 @@
 
 int unregister_chrdev(unsigned int major, const char * name)
 {
+	if (devfs_only())
+		return 0;
 	if (major >= MAX_CHRDEV)
 		return -EINVAL;
 	write_lock(&chrdevs_lock);
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	Thu Aug  1 14:17:36 2002
+++ b/fs/direct-io.c	Thu Aug  1 14:17:36 2002
@@ -13,6 +13,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/bio.h>
 #include <linux/wait.h>
@@ -39,13 +40,17 @@
 	struct bio_vec *bvec;		/* current bvec in that bio */
 	struct inode *inode;
 	int rw;
+	unsigned blkbits;		/* doesn't change */
 	sector_t block_in_file;		/* changes */
+	unsigned blocks_available;	/* At block_in_file.  changes */
 	sector_t final_block_in_request;/* doesn't change */
-	unsigned first_block_in_page;	/* doesn't change */
+	unsigned first_block_in_page;	/* doesn't change, Used only once */
 	int boundary;			/* prev block is at a boundary */
 	int reap_counter;		/* rate limit reaping */
-	get_block_t *get_block;
-	sector_t last_block_in_bio;
+	get_blocks_t *get_blocks;	/* block mapping function */
+	sector_t last_block_in_bio;	/* current final block in bio */
+	sector_t next_block_in_bio;	/* next block to be added to bio */
+	struct buffer_head map_bh;	/* last get_blocks() result */
 
 	/* Page fetching state */
 	int curr_page;			/* changes */
@@ -53,15 +58,16 @@
 	unsigned long curr_user_address;/* changes */
 
 	/* Page queue */
-	struct page *pages[DIO_PAGES];
-	unsigned head;
-	unsigned tail;
+	struct page *pages[DIO_PAGES];	/* page buffer */
+	unsigned head;			/* next page to process */
+	unsigned tail;			/* last valid page + 1 */
+	int page_errors;		/* errno from get_user_pages() */
 
 	/* BIO completion state */
-	atomic_t bio_count;
-	spinlock_t bio_list_lock;
+	atomic_t bio_count;		/* nr bios in flight */
+	spinlock_t bio_list_lock;	/* protects bio_list */
 	struct bio *bio_list;		/* singly linked via bi_private */
-	struct task_struct *waiter;
+	struct task_struct *waiter;	/* waiting task (NULL if none) */
 };
 
 /*
@@ -93,6 +99,21 @@
 		NULL);				/* vmas */
 	up_read(&current->mm->mmap_sem);
 
+	if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) {
+		/*
+		 * A memory fault, but the filesystem has some outstanding
+		 * mapped blocks.  We need to use those blocks up to avoid
+		 * leaking stale data in the file.
+		 */
+		if (dio->page_errors == 0)
+			dio->page_errors = ret;
+		dio->pages[0] = ZERO_PAGE(dio->cur_user_address);
+		dio->head = 0;
+		dio->tail = 1;
+		ret = 0;
+		goto out;
+	}
+
 	if (ret >= 0) {
 		dio->curr_user_address += ret * PAGE_SIZE;
 		dio->curr_page += ret;
@@ -100,6 +121,7 @@
 		dio->tail = ret;
 		ret = 0;
 	}
+out:
 	return ret;	
 }
 
@@ -115,11 +137,8 @@
 		int ret;
 
 		ret = dio_refill_pages(dio);
-		if (ret) {
-			printk("%s: dio_refill_pages returns %d\n",
-				__FUNCTION__, ret);
+		if (ret)
 			return ERR_PTR(ret);
-		}
 		BUG_ON(dio_pages_present(dio) == 0);
 	}
 	return dio->pages[dio->head++];
@@ -140,8 +159,9 @@
 	spin_lock_irqsave(&dio->bio_list_lock, flags);
 	bio->bi_private = dio->bio_list;
 	dio->bio_list = bio;
+	if (dio->waiter)
+		wake_up_process(dio->waiter);
 	spin_unlock_irqrestore(&dio->bio_list_lock, flags);
-	wake_up_process(dio->waiter);
 }
 
 static int
@@ -179,6 +199,7 @@
 
 	dio->bio = NULL;
 	dio->bvec = NULL;
+	dio->boundary = 0;
 }
 
 /*
@@ -202,10 +223,12 @@
 	while (dio->bio_list == NULL) {
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		if (dio->bio_list == NULL) {
+			dio->waiter = current;
 			spin_unlock_irqrestore(&dio->bio_list_lock, flags);
 			blk_run_queues();
 			schedule();
 			spin_lock_irqsave(&dio->bio_list_lock, flags);
+			dio->waiter = NULL;
 		}
 		set_current_state(TASK_RUNNING);
 	}
@@ -268,15 +291,12 @@
 		while (dio->bio_list) {
 			unsigned long flags;
 			struct bio *bio;
-			int ret2;
 
 			spin_lock_irqsave(&dio->bio_list_lock, flags);
 			bio = dio->bio_list;
 			dio->bio_list = bio->bi_private;
 			spin_unlock_irqrestore(&dio->bio_list_lock, flags);
-			ret2 = dio_bio_complete(dio, bio);
-			if (ret == 0)
-				ret = ret2;
+			ret = dio_bio_complete(dio, bio);
 		}
 		dio->reap_counter = 0;
 	}
@@ -284,13 +304,129 @@
 }
 
 /*
+ * Call into the fs to map some more disk blocks.  We record the current number
+ * of available blocks at dio->blocks_available.  These are in units of the
+ * fs blocksize, (1 << inode->i_blkbits).
+ *
+ * The fs is allowed to map lots of blocks at once.  If it wants to do that,
+ * it uses the passed inode-relative block number as the file offset, as usual.
+ *
+ * get_blocks() is passed the number of i_blkbits-sized blocks which direct_io
+ * has remaining to do.  The fs should not map more than this number of blocks.
+ *
+ * If the fs has mapped a lot of blocks, it should populate bh->b_size to
+ * indicate how much contiguous disk space has been made available at
+ * bh->b_blocknr.
+ *
+ * If *any* of the mapped blocks are new, then the fs must set buffer_new().
+ * This isn't very efficient...
+ *
+ * In the case of filesystem holes: the fs may return an arbitrarily-large
+ * hole by returning an appropriate value in b_size and by clearing
+ * buffer_mapped().  This code _should_ handle that case correctly, but it has
+ * only been tested against single-block holes (b_size == blocksize).
+ */
+static int get_more_blocks(struct dio *dio)
+{
+	int ret;
+	struct buffer_head *map_bh = &dio->map_bh;
+
+	if (dio->blocks_available)
+		return 0;
+
+	/*
+	 * If there was a memory error and we've overwritten all the
+	 * mapped blocks then we can now return that memory error
+	 */
+	if (dio->page_errors) {
+		ret = dio->page_errors;
+		goto out;
+	}
+
+	map_bh->b_state = 0;
+	map_bh->b_size = 0;
+	BUG_ON(dio->block_in_file >= dio->final_block_in_request);
+	ret = (*dio->get_blocks)(dio->inode, dio->block_in_file,
+			dio->final_block_in_request - dio->block_in_file,
+			map_bh, dio->rw == WRITE);
+	if (ret)
+		goto out;
+
+	if (buffer_mapped(map_bh)) {
+		BUG_ON(map_bh->b_size == 0);
+		BUG_ON((map_bh->b_size & ((1 << dio->blkbits) - 1)) != 0);
+
+		dio->blocks_available = map_bh->b_size >> dio->blkbits;
+
+		/* blockdevs do not set buffer_new */
+		if (buffer_new(map_bh)) {
+			sector_t block = map_bh->b_blocknr;
+			unsigned i;
+
+			for (i = 0; i < dio->blocks_available; i++)
+				unmap_underlying_metadata(map_bh->b_bdev,
+							block++);
+		}
+	} else {
+		BUG_ON(dio->rw != READ);
+		if (dio->bio)
+			dio_bio_submit(dio);
+	}
+	dio->next_block_in_bio = map_bh->b_blocknr;
+out:
+	return ret;
+}
+
+/*
+ * Check to see if we can continue to grow the BIO. If not, then send it.
+ */
+static void dio_prep_bio(struct dio *dio)
+{
+	if (dio->bio == NULL)
+		return;
+
+	if (dio->bio->bi_idx == dio->bio->bi_vcnt ||
+			dio->boundary ||
+			dio->last_block_in_bio != dio->next_block_in_bio - 1)
+		dio_bio_submit(dio);
+}
+
+/*
+ * There is no bio.  Make one now.
+ */
+static int dio_new_bio(struct dio *dio)
+{
+	sector_t sector;
+	int ret;
+
+	ret = dio_bio_reap(dio);
+	if (ret)
+		goto out;
+	sector = dio->next_block_in_bio << (dio->blkbits - 9);
+	ret = dio_bio_alloc(dio, dio->map_bh.b_bdev, sector,
+				DIO_BIO_MAX_SIZE / PAGE_SIZE);
+	dio->boundary = 0;
+out:
+	return ret;
+}
+
+/*
  * Walk the user pages, and the file, mapping blocks to disk and emitting BIOs.
+ *
+ * Direct IO against a blockdev is different from a file.  Because we can
+ * happily perform page-sized but 512-byte aligned IOs.  It is important that
+ * blockdev IO be able to have fine alignment and large sizes.
+ *
+ * So what we do is to permit the ->get_blocks function to populate bh.b_size
+ * with the size of IO which is permitted at this offset and this i_blkbits.
+ *
+ * For best results, the blockdev should be set up with 512-byte i_blkbits and
+ * it should set b_size to PAGE_SIZE or more inside get_blocks().  This gives
+ * fine alignment but still allows this function to work in PAGE_SIZE units.
  */
 int do_direct_IO(struct dio *dio)
 {
-	struct inode * const inode = dio->inode;
-	const unsigned blkbits = inode->i_blkbits;
-	const unsigned blocksize = 1 << blkbits;
+	const unsigned blkbits = dio->blkbits;
 	const unsigned blocks_per_page = PAGE_SIZE >> blkbits;
 	struct page *page;
 	unsigned block_in_page;
@@ -309,46 +445,35 @@
 		}
 
 		new_page = 1;
-		for ( ; block_in_page < blocks_per_page; block_in_page++) {
-			struct buffer_head map_bh;
+		while (block_in_page < blocks_per_page) {
 			struct bio *bio;
+			unsigned this_chunk_bytes;	/* # of bytes mapped */
+			unsigned this_chunk_blocks;	/* # of blocks */
+			unsigned u;
 
-			map_bh.b_state = 0;
-			ret = (*dio->get_block)(inode, dio->block_in_file,
-						&map_bh, dio->rw == WRITE);
-			if (ret) {
-				printk("%s: get_block returns %d\n",
-					__FUNCTION__, ret);
+			ret = get_more_blocks(dio);
+			if (ret)
 				goto fail_release;
+
+			/* Handle holes */
+			if (!buffer_mapped(&dio->map_bh)) {
+				char *kaddr = kmap_atomic(page, KM_USER0);
+				memset(kaddr + (block_in_page << blkbits),
+						0, 1 << blkbits);
+				flush_dcache_page(page);
+				kunmap_atomic(kaddr, KM_USER0);
+				dio->block_in_file++;
+				dio->next_block_in_bio++;
+				block_in_page++;
+				goto next_block;
 			}
-			/* blockdevs do not set buffer_new */
-			if (buffer_new(&map_bh))
-				unmap_underlying_metadata(map_bh.b_bdev,
-							map_bh.b_blocknr);
-			if (!buffer_mapped(&map_bh)) {
-				ret = -EINVAL;		/* A hole */
-				goto fail_release;
-			}
-			if (dio->bio) {
-				if (dio->bio->bi_idx == dio->bio->bi_vcnt ||
-						dio->boundary ||
-						dio->last_block_in_bio !=
-							map_bh.b_blocknr - 1) {
-					dio_bio_submit(dio);
-					dio->boundary = 0;
-				}
-			}
+
+			dio_prep_bio(dio);
 			if (dio->bio == NULL) {
-				ret = dio_bio_reap(dio);
-				if (ret)
-					goto fail_release;
-				ret = dio_bio_alloc(dio, map_bh.b_bdev,
-					map_bh.b_blocknr << (blkbits - 9),
-					DIO_BIO_MAX_SIZE / PAGE_SIZE);
+				ret = dio_new_bio(dio);
 				if (ret)
 					goto fail_release;
 				new_page = 1;
-				dio->boundary = 0;
 			}
 
 			bio = dio->bio;
@@ -357,17 +482,34 @@
 				page_cache_get(page);
 				dio->bvec->bv_page = page;
 				dio->bvec->bv_len = 0;
-				dio->bvec->bv_offset = block_in_page*blocksize;
+				dio->bvec->bv_offset = block_in_page << blkbits;
 				bio->bi_idx++;
+				new_page = 0;
 			}
-			new_page = 0;
-			dio->bvec->bv_len += blocksize;
-			bio->bi_size += blocksize;
-			dio->last_block_in_bio = map_bh.b_blocknr;
-			dio->boundary = buffer_boundary(&map_bh);
 
-			dio->block_in_file++;
-			if (dio->block_in_file >= dio->final_block_in_request)
+			/* Work out how much disk we can add to this page */
+			this_chunk_blocks = dio->blocks_available;
+			u = (PAGE_SIZE - dio->bvec->bv_len) >> blkbits;
+			if (this_chunk_blocks > u)
+				this_chunk_blocks = u;
+			u = dio->final_block_in_request - dio->block_in_file;
+			if (this_chunk_blocks > u)
+				this_chunk_blocks = u;
+			this_chunk_bytes = this_chunk_blocks << blkbits;
+			BUG_ON(this_chunk_bytes == 0);
+
+			dio->bvec->bv_len += this_chunk_bytes;
+			bio->bi_size += this_chunk_bytes;
+			dio->next_block_in_bio += this_chunk_blocks;
+			dio->last_block_in_bio = dio->next_block_in_bio - 1;
+			dio->boundary = buffer_boundary(&dio->map_bh);
+			dio->block_in_file += this_chunk_blocks;
+			block_in_page += this_chunk_blocks;
+			dio->blocks_available -= this_chunk_blocks;
+next_block:
+			if (dio->block_in_file > dio->final_block_in_request)
+				BUG();
+			if (dio->block_in_file == dio->final_block_in_request)
 				break;
 		}
 		block_in_page = 0;
@@ -381,11 +523,16 @@
 	return ret;
 }
 
+/*
+ * The main direct-IO function.  This is a library function for use by
+ * filesystem drivers.
+ */
 int
 generic_direct_IO(int rw, struct inode *inode, char *buf, loff_t offset,
-			size_t count, get_block_t get_block)
+			size_t count, get_blocks_t get_blocks)
 {
-	const unsigned blocksize_mask = (1 << inode->i_blkbits) - 1;
+	const unsigned blkbits = inode->i_blkbits;
+	const unsigned blocksize_mask = (1 << blkbits) - 1;
 	const unsigned long user_addr = (unsigned long)buf;
 	int ret;
 	int ret2;
@@ -403,16 +550,18 @@
 	dio.bvec = NULL;
 	dio.inode = inode;
 	dio.rw = rw;
-	dio.block_in_file = offset >> inode->i_blkbits;
-	dio.final_block_in_request = (offset + count) >> inode->i_blkbits;
+	dio.blkbits = blkbits;
+	dio.block_in_file = offset >> blkbits;
+	dio.blocks_available = 0;
+	dio.final_block_in_request = (offset + count) >> blkbits;
 
 	/* Index into the first page of the first block */
-	dio.first_block_in_page = (user_addr & (PAGE_SIZE - 1))
-						>> inode->i_blkbits;
+	dio.first_block_in_page = (user_addr & (PAGE_SIZE - 1)) >> blkbits;
 	dio.boundary = 0;
 	dio.reap_counter = 0;
-	dio.get_block = get_block;
+	dio.get_blocks = get_blocks;
 	dio.last_block_in_bio = -1;
+	dio.next_block_in_bio = -1;
 
 	/* Page fetching state */
 	dio.curr_page = 0;
@@ -428,12 +577,13 @@
 	/* Page queue */
 	dio.head = 0;
 	dio.tail = 0;
+	dio.page_errors = 0;
 
 	/* BIO completion state */
 	atomic_set(&dio.bio_count, 0);
 	spin_lock_init(&dio.bio_list_lock);
 	dio.bio_list = NULL;
-	dio.waiter = current;
+	dio.waiter = NULL;
 
 	ret = do_direct_IO(&dio);
 
@@ -445,8 +595,10 @@
 	if (ret == 0)
 		ret = ret2;
 	if (ret == 0)
+		ret = dio.page_errors;
+	if (ret == 0)
 		ret = count - ((dio.final_block_in_request -
-				dio.block_in_file) << inode->i_blkbits);
+				dio.block_in_file) << blkbits);
 out:
 	return ret;
 }
@@ -473,6 +625,8 @@
 			goto out;
 	}
 	retval = mapping->a_ops->direct_IO(rw, inode, buf, offset, count);
+	if (inode->i_mapping->nrpages)
+		invalidate_inode_pages2(inode->i_mapping);
 out:
 	return retval;
 }
diff -Nru a/fs/driverfs/inode.c b/fs/driverfs/inode.c
--- a/fs/driverfs/inode.c	Thu Aug  1 14:17:36 2002
+++ b/fs/driverfs/inode.c	Thu Aug  1 14:17:36 2002
@@ -32,7 +32,7 @@
 #include <linux/namei.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/device.h>
+#include <linux/driverfs_fs.h>
 
 #include <asm/uaccess.h>
 
@@ -50,7 +50,6 @@
 static struct super_operations driverfs_ops;
 static struct file_operations driverfs_file_operations;
 static struct inode_operations driverfs_dir_inode_operations;
-static struct dentry_operations driverfs_dentry_file_ops;
 static struct address_space_operations driverfs_aops;
 
 static struct vfsmount *driverfs_mount;
@@ -139,7 +138,7 @@
 
 	/* only allow create if ->d_fsdata is not NULL (so we can assume it 
 	 * comes from the driverfs API below. */
-	if (dentry->d_fsdata && inode) {
+	if (inode) {
 		d_instantiate(dentry, inode);
 		dget(dentry);
 		error = 0;
@@ -161,7 +160,6 @@
 {
 	int res;
 	mode = (mode & S_IALLUGO) | S_IFREG;
-	dentry->d_op = &driverfs_dentry_file_ops;
  	res = driverfs_mknod(dir, dentry, mode, 0);
 	return res;
 }
@@ -268,7 +266,7 @@
  *
  * Userspace wants data from a file. It is up to the creator of the file to
  * provide that data.
- * There is a struct driver_file_entry embedded in file->private_data. We
+ * There is a struct device_attribute embedded in file->private_data. We
  * obtain that and check if the read callback is implemented. If so, we call
  * it, passing the data field of the file entry.
  * Said callback is responsible for filling the buffer and returning the number
@@ -277,24 +275,18 @@
 static ssize_t
 driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
 {
-	struct driver_file_entry * entry;
+	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct driver_dir_entry * dir;
 	unsigned char *page;
 	ssize_t retval = 0;
-	struct device * dev;
 
-	entry = (struct driver_file_entry *)file->private_data;
-	if (!entry) {
-		DBG("%s: file entry is NULL\n",__FUNCTION__);
-		return -ENOENT;
-	}
-	if (!entry->show)
+	dir = file->f_dentry->d_parent->d_fsdata;
+	if (!dir->ops->show)
 		return 0;
 
 	if (count > PAGE_SIZE)
 		count = PAGE_SIZE;
 
-	dev = to_device(entry->parent);
-
 	page = (unsigned char*)__get_free_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
@@ -302,7 +294,7 @@
 	while (count > 0) {
 		ssize_t len;
 
-		len = entry->show(dev,page,count,*ppos);
+		len = dir->ops->show(dir,attr,page,count,*ppos);
 
 		if (len <= 0) {
 			if (len < 0)
@@ -341,20 +333,12 @@
 static ssize_t
 driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
 {
-	struct driver_file_entry * entry;
-	struct device * dev;
+	struct attribute * attr = file->f_dentry->d_fsdata;
+	struct driver_dir_entry * dir;
 	ssize_t retval = 0;
 	char * page;
 
-	entry = (struct driver_file_entry *)file->private_data;
-	if (!entry) {
-		DBG("%s: file entry is NULL\n",__FUNCTION__);
-		return -ENOENT;
-	}
-	if (!entry->store)
-		return 0;
-
-	dev = to_device(entry->parent);
+	dir = file->f_dentry->d_parent->d_fsdata;
 
 	page = (char *)__get_free_page(GFP_KERNEL);
 	if (!page)
@@ -369,7 +353,7 @@
 	while (count > 0) {
 		ssize_t len;
 
-		len = entry->store(dev,page + retval,count,*ppos);
+		len = dir->ops->store(dir,attr,page + retval,count,*ppos);
 
 		if (len <= 0) {
 			if (len < 0)
@@ -414,38 +398,29 @@
 
 static int driverfs_open_file(struct inode * inode, struct file * filp)
 {
-	struct driver_file_entry * entry;
-	struct device * dev;
+	struct driver_dir_entry * dir;
+	int error = 0;
 
-	entry = (struct driver_file_entry *)inode->u.generic_ip;
-	if (!entry)
-		return -EFAULT;
-	dev = to_device(entry->parent);
-	get_device(dev);
-	filp->private_data = entry;
-	return 0;
+	dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
+	if (dir) {
+		struct attribute * attr = filp->f_dentry->d_fsdata;
+		if (attr && dir->ops) {
+			if (dir->ops->open)
+				error = dir->ops->open(dir);
+			goto Done;
+		}
+	}
+	error = -EINVAL;
+ Done:
+	return error;
 }
 
 static int driverfs_release(struct inode * inode, struct file * filp)
 {
-	struct driver_file_entry * entry;
-	struct device * dev;
-
-	entry = (struct driver_file_entry *)filp->private_data;
-	if (!entry)
-		return -EFAULT;
-	dev = to_device(entry->parent);
-	put_device(dev);
-	return 0;
-}
-
-static int driverfs_d_delete_file (struct dentry * dentry)
-{
-	struct driver_file_entry * entry;
-
-	entry = (struct driver_file_entry *)dentry->d_fsdata;
-	if (entry)
-		kfree(entry);
+	struct driver_dir_entry * dir;
+	dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
+	if (dir->ops->close)
+		dir->ops->close(dir);
 	return 0;
 }
 
@@ -468,10 +443,6 @@
 	.commit_write	= driverfs_commit_write
 };
 
-static struct dentry_operations driverfs_dentry_file_ops = {
-	.d_delete	= driverfs_d_delete_file,
-};
-
 static struct super_operations driverfs_ops = {
 	.statfs		= simple_statfs,
 	.drop_inode	= generic_delete_inode,
@@ -572,6 +543,16 @@
 	return register_filesystem(&driverfs_fs_type);
 }
 
+static struct dentry * get_dentry(struct dentry * parent, const char * name)
+{
+	struct qstr qstr;
+
+	qstr.name = name;
+	qstr.len = strlen(name);
+	qstr.hash = full_name_hash(name,qstr.len);
+	return lookup_hash(&qstr,parent);
+}
+
 /**
  * driverfs_create_dir - create a directory in the filesystem
  * @entry:	directory entry
@@ -583,7 +564,6 @@
 {
 	struct dentry * dentry = NULL;
 	struct dentry * parent_dentry;
-	struct qstr qstr;
 	int error = 0;
 
 	if (!entry)
@@ -603,10 +583,7 @@
 	}
 
 	down(&parent_dentry->d_inode->i_sem);
-	qstr.name = entry->name;
-	qstr.len = strlen(entry->name);
-	qstr.hash = full_name_hash(entry->name,qstr.len);
-	dentry = lookup_hash(&qstr,parent_dentry);
+	dentry = get_dentry(parent_dentry,entry->name);
 	if (!IS_ERR(dentry)) {
 		dentry->d_fsdata = (void *) entry;
 		entry->dentry = dentry;
@@ -626,11 +603,10 @@
  * @parent:	directory to create it in
  */
 int
-driverfs_create_file(struct driver_file_entry * entry,
+driverfs_create_file(struct attribute * entry,
 		     struct driver_dir_entry * parent)
 {
 	struct dentry * dentry;
-	struct qstr qstr;
 	int error = 0;
 
 	if (!entry || !parent)
@@ -645,21 +621,10 @@
 	}
 
 	down(&parent->dentry->d_inode->i_sem);
-	qstr.name = entry->name;
-	qstr.len = strlen(entry->name);
-	qstr.hash = full_name_hash(entry->name,qstr.len);
-	dentry = lookup_hash(&qstr,parent->dentry);
+	dentry = get_dentry(parent->dentry,entry->name);
 	if (!IS_ERR(dentry)) {
 		dentry->d_fsdata = (void *)entry;
 		error = driverfs_create(parent->dentry->d_inode,dentry,entry->mode);
-
-		/* Still good? Ok, then fill in the blanks: */
-		if (!error) {
-			dentry->d_inode->u.generic_ip = (void *)entry;
-			entry->dentry = dentry;
-			entry->parent = parent;
-			list_add_tail(&entry->node,&parent->files);
-		}
 	} else
 		error = PTR_ERR(dentry);
 	up(&parent->dentry->d_inode->i_sem);
@@ -676,14 +641,12 @@
  * 
  */
 int driverfs_create_symlink(struct driver_dir_entry * parent, 
-			    struct driver_file_entry * entry,
-			    char * target)
+			    char * name, char * target)
 {
 	struct dentry * dentry;
-	struct qstr qstr;
 	int error = 0;
 
-	if (!entry || !parent)
+	if (!parent)
 		return -EINVAL;
 
 	get_mount();
@@ -693,20 +656,10 @@
 		return -EINVAL;
 	}
 	down(&parent->dentry->d_inode->i_sem);
-	qstr.name = entry->name;
-	qstr.len = strlen(entry->name);
-	qstr.hash = full_name_hash(entry->name,qstr.len);
-	dentry = lookup_hash(&qstr,parent->dentry);
-	if (!IS_ERR(dentry)) {
-		dentry->d_fsdata = (void *)entry;
+	dentry = get_dentry(parent->dentry,name);
+	if (!IS_ERR(dentry))
 		error = driverfs_symlink(parent->dentry->d_inode,dentry,target);
-		if (!error) {
-			dentry->d_inode->u.generic_ip = (void *)entry;
-			entry->dentry = dentry;
-			entry->parent = parent;
-			list_add_tail(&entry->node,&parent->files);
-		}
-	} else
+	else
 		error = PTR_ERR(dentry);
 	up(&parent->dentry->d_inode->i_sem);
 	if (error)
@@ -724,26 +677,21 @@
  */
 void driverfs_remove_file(struct driver_dir_entry * dir, const char * name)
 {
-	struct list_head * node;
+	struct dentry * dentry;
 
 	if (!dir->dentry)
 		return;
 
 	down(&dir->dentry->d_inode->i_sem);
-
-	node = dir->files.next;
-	while (node != &dir->files) {
-		struct driver_file_entry * entry = NULL;
-
-		entry = list_entry(node,struct driver_file_entry,node);
-		if (!strcmp(entry->name,name)) {
-			list_del_init(node);
-			driverfs_unlink(entry->dentry->d_parent->d_inode,entry->dentry);
-			dput(entry->dentry);
+	dentry = get_dentry(dir->dentry,name);
+	if (!IS_ERR(dentry)) {
+		/* make sure dentry is really there */
+		if (dentry->d_inode && 
+		    (dentry->d_parent->d_inode == dir->dentry->d_inode)) {
+			driverfs_unlink(dir->dentry->d_inode,dentry);
+			dput(dir->dentry);
 			put_mount();
-			break;
 		}
-		node = node->next;
 	}
 	up(&dir->dentry->d_inode->i_sem);
 }
@@ -767,19 +715,16 @@
 	down(&dentry->d_parent->d_inode->i_sem);
 	down(&dentry->d_inode->i_sem);
 
-	node = dir->files.next;
-	while (node != &dir->files) {
-		struct driver_file_entry * entry;
-		entry = list_entry(node,struct driver_file_entry,node);
-
-		list_del_init(node);
-		driverfs_unlink(dentry->d_inode,entry->dentry);
-		dput(entry->dentry);
+	node = dentry->d_subdirs.next;
+	while (node != &dentry->d_subdirs) {
+		struct dentry * d = list_entry(node,struct dentry,d_child);
+
+		node = node->next;
+		driverfs_unlink(dentry->d_inode,d);
+		dput(dentry);
 		put_mount();
-		node = dir->files.next;
 	}
 	up(&dentry->d_inode->i_sem);
-
 	driverfs_rmdir(dentry->d_parent->d_inode,dentry);
 	up(&dentry->d_parent->d_inode->i_sem);
 	dput(dentry);
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	Thu Aug  1 14:17:40 2002
+++ b/fs/exec.c	Thu Aug  1 14:17:40 2002
@@ -313,8 +313,13 @@
 
 	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (!mpnt) 
-		return -ENOMEM; 
-	
+		return -ENOMEM;
+
+	if (!vm_enough_memory((STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))>>PAGE_SHIFT)) {
+		kmem_cache_free(vm_area_cachep, mpnt);
+		return -ENOMEM;
+	}
+
 	down_write(&current->mm->mmap_sem);
 	{
 		mpnt->vm_mm = current->mm;
diff -Nru a/fs/ext2/file.c b/fs/ext2/file.c
--- a/fs/ext2/file.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ext2/file.c	Thu Aug  1 14:17:40 2002
@@ -46,6 +46,7 @@
 	open:		generic_file_open,
 	release:	ext2_release_file,
 	fsync:		ext2_sync_file,
+	sendfile:	generic_file_sendfile,
 };
 
 struct inode_operations ext2_file_inode_operations = {
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	Thu Aug  1 14:17:36 2002
+++ b/fs/ext2/inode.c	Thu Aug  1 14:17:36 2002
@@ -607,10 +607,23 @@
 }
 
 static int
+ext2_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
+			struct buffer_head *bh_result, int create)
+{
+	int ret;
+
+	ret = ext2_get_block(inode, iblock, bh_result, create);
+	if (ret == 0)
+		bh_result->b_size = (1 << inode->i_blkbits);
+	return ret;
+}
+
+static int
 ext2_direct_IO(int rw, struct inode *inode, char *buf,
 			loff_t offset, size_t count)
 {
-	return generic_direct_IO(rw, inode, buf, offset, count, ext2_get_block);
+	return generic_direct_IO(rw, inode, buf,
+				offset, count, ext2_get_blocks);
 }
 
 static int
diff -Nru a/fs/ext3/dir.c b/fs/ext3/dir.c
--- a/fs/ext3/dir.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ext3/dir.c	Thu Aug  1 14:17:40 2002
@@ -31,10 +31,10 @@
 static int ext3_readdir(struct file *, void *, filldir_t);
 
 struct file_operations ext3_dir_operations = {
-	read:		generic_read_dir,
-	readdir:	ext3_readdir,		/* we take BKL. needed?*/
-	ioctl:		ext3_ioctl,		/* BKL held */
-	fsync:		ext3_sync_file,		/* BKL held */
+	.read		= generic_read_dir,
+	.readdir	= ext3_readdir,		/* we take BKL. needed?*/
+	.ioctl		= ext3_ioctl,		/* BKL held */
+	.fsync		= ext3_sync_file,		/* BKL held */
 };
 
 int ext3_check_dir_entry (const char * function, struct inode * dir,
diff -Nru a/fs/ext3/file.c b/fs/ext3/file.c
--- a/fs/ext3/file.c	Thu Aug  1 14:17:41 2002
+++ b/fs/ext3/file.c	Thu Aug  1 14:17:41 2002
@@ -76,18 +76,19 @@
 }
 
 struct file_operations ext3_file_operations = {
-	llseek:		generic_file_llseek,	/* BKL held */
-	read:		generic_file_read,	/* BKL not held.  Don't need */
-	write:		ext3_file_write,	/* BKL not held.  Don't need */
-	ioctl:		ext3_ioctl,		/* BKL held */
-	mmap:		generic_file_mmap,
-	open:		ext3_open_file,		/* BKL not held.  Don't need */
-	release:	ext3_release_file,	/* BKL not held.  Don't need */
-	fsync:		ext3_sync_file,		/* BKL held */
+	.llseek		= generic_file_llseek,	/* BKL held */
+	.read		= generic_file_read,	/* BKL not held.  Don't need */
+	.write		= ext3_file_write,	/* BKL not held.  Don't need */
+	.ioctl		= ext3_ioctl,		/* BKL held */
+	.mmap		= generic_file_mmap,
+	.open		= ext3_open_file,		/* BKL not held.  Don't need */
+	.release	= ext3_release_file,	/* BKL not held.  Don't need */
+	.fsync		= ext3_sync_file,		/* BKL held */
+	.sendfile	= generic_file_sendfile,	/* BKL not held.  Don't need */
 };
 
 struct inode_operations ext3_file_inode_operations = {
-	truncate:	ext3_truncate,		/* BKL held */
-	setattr:	ext3_setattr,		/* BKL held */
+	.truncate	= ext3_truncate,		/* BKL held */
+	.setattr	= ext3_setattr,		/* BKL held */
 };
 
diff -Nru a/fs/ext3/inode.c b/fs/ext3/inode.c
--- a/fs/ext3/inode.c	Thu Aug  1 14:17:41 2002
+++ b/fs/ext3/inode.c	Thu Aug  1 14:17:41 2002
@@ -1378,15 +1378,15 @@
 
 
 struct address_space_operations ext3_aops = {
-	readpage:	ext3_readpage,		/* BKL not held.  Don't need */
-	readpages:	ext3_readpages,		/* BKL not held.  Don't need */
-	writepage:	ext3_writepage,		/* BKL not held.  We take it */
-	sync_page:	block_sync_page,
-	prepare_write:	ext3_prepare_write,	/* BKL not held.  We take it */
-	commit_write:	ext3_commit_write,	/* BKL not held.  We take it */
-	bmap:		ext3_bmap,		/* BKL held */
-	invalidatepage:	ext3_invalidatepage,	/* BKL not held.  Don't need */
-	releasepage:	ext3_releasepage,	/* BKL not held.  Don't need */
+	.readpage	= ext3_readpage,		/* BKL not held.  Don't need */
+	.readpages	= ext3_readpages,		/* BKL not held.  Don't need */
+	.writepage	= ext3_writepage,		/* BKL not held.  We take it */
+	.sync_page	= block_sync_page,
+	.prepare_write	= ext3_prepare_write,	/* BKL not held.  We take it */
+	.commit_write	= ext3_commit_write,	/* BKL not held.  We take it */
+	.bmap		= ext3_bmap,		/* BKL held */
+	.invalidatepage	= ext3_invalidatepage,	/* BKL not held.  Don't need */
+	.releasepage	= ext3_releasepage,	/* BKL not held.  Don't need */
 };
 
 /* For writeback mode, we can use mpage_writepages() */
@@ -1405,16 +1405,16 @@
 }
 
 struct address_space_operations ext3_writeback_aops = {
-	readpage:	ext3_readpage,		/* BKL not held.  Don't need */
-	readpages:	ext3_readpages,		/* BKL not held.  Don't need */
-	writepage:	ext3_writepage,		/* BKL not held.  We take it */
-	writepages:	ext3_writepages,	/* BKL not held.  Don't need */
-	sync_page:	block_sync_page,
-	prepare_write:	ext3_prepare_write,	/* BKL not held.  We take it */
-	commit_write:	ext3_commit_write,	/* BKL not held.  We take it */
-	bmap:		ext3_bmap,		/* BKL held */
-	invalidatepage:	ext3_invalidatepage,	/* BKL not held.  Don't need */
-	releasepage:	ext3_releasepage,	/* BKL not held.  Don't need */
+	.readpage	= ext3_readpage,		/* BKL not held.  Don't need */
+	.readpages	= ext3_readpages,		/* BKL not held.  Don't need */
+	.writepage	= ext3_writepage,		/* BKL not held.  We take it */
+	.writepages	= ext3_writepages,	/* BKL not held.  Don't need */
+	.sync_page	= block_sync_page,
+	.prepare_write	= ext3_prepare_write,	/* BKL not held.  We take it */
+	.commit_write	= ext3_commit_write,	/* BKL not held.  We take it */
+	.bmap		= ext3_bmap,		/* BKL held */
+	.invalidatepage	= ext3_invalidatepage,	/* BKL not held.  Don't need */
+	.releasepage	= ext3_releasepage,	/* BKL not held.  Don't need */
 };
 
 /*
diff -Nru a/fs/ext3/namei.c b/fs/ext3/namei.c
--- a/fs/ext3/namei.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ext3/namei.c	Thu Aug  1 14:17:40 2002
@@ -1194,13 +1194,13 @@
  * directories can handle most operations...
  */
 struct inode_operations ext3_dir_inode_operations = {
-	create:		ext3_create,
-	lookup:		ext3_lookup,
-	link:		ext3_link,
-	unlink:		ext3_unlink,
-	symlink:	ext3_symlink,
-	mkdir:		ext3_mkdir,
-	rmdir:		ext3_rmdir,
-	mknod:		ext3_mknod,
-	rename:		ext3_rename,
+	.create		= ext3_create,
+	.lookup		= ext3_lookup,
+	.link		= ext3_link,
+	.unlink		= ext3_unlink,
+	.symlink	= ext3_symlink,
+	.mkdir		= ext3_mkdir,
+	.rmdir		= ext3_rmdir,
+	.mknod		= ext3_mknod,
+	.rename		= ext3_rename,
 };
diff -Nru a/fs/ext3/super.c b/fs/ext3/super.c
--- a/fs/ext3/super.c	Thu Aug  1 14:17:41 2002
+++ b/fs/ext3/super.c	Thu Aug  1 14:17:41 2002
@@ -489,24 +489,24 @@
 }
 
 static struct super_operations ext3_sops = {
-	alloc_inode:	ext3_alloc_inode,
-	destroy_inode:	ext3_destroy_inode,
-	read_inode:	ext3_read_inode,	/* BKL held */
-	write_inode:	ext3_write_inode,	/* BKL not held.  Don't need */
-	dirty_inode:	ext3_dirty_inode,	/* BKL not held.  We take it */
-	put_inode:	ext3_put_inode,		/* BKL not held.  Don't need */
-	delete_inode:	ext3_delete_inode,	/* BKL not held.  We take it */
-	put_super:	ext3_put_super,		/* BKL held */
-	write_super:	ext3_write_super,	/* BKL not held. We take it. Needed? */
-	write_super_lockfs: ext3_write_super_lockfs, /* BKL not held. Take it */
-	unlockfs:	ext3_unlockfs,		/* BKL not held.  We take it */
-	statfs:		ext3_statfs,		/* BKL not held. */
-	remount_fs:	ext3_remount,		/* BKL held */
+	.alloc_inode	= ext3_alloc_inode,
+	.destroy_inode	= ext3_destroy_inode,
+	.read_inode	= ext3_read_inode,	/* BKL held */
+	.write_inode	= ext3_write_inode,	/* BKL not held.  Don't need */
+	.dirty_inode	= ext3_dirty_inode,	/* BKL not held.  We take it */
+	.put_inode	= ext3_put_inode,		/* BKL not held.  Don't need */
+	.delete_inode	= ext3_delete_inode,	/* BKL not held.  We take it */
+	.put_super	= ext3_put_super,		/* BKL held */
+	.write_super	= ext3_write_super,	/* BKL not held. We take it. Needed? */
+	.write_super_lockfs = ext3_write_super_lockfs, /* BKL not held. Take it */
+	.unlockfs	= ext3_unlockfs,		/* BKL not held.  We take it */
+	.statfs		= ext3_statfs,		/* BKL not held. */
+	.remount_fs	= ext3_remount,		/* BKL held */
 };
 
 struct dentry *ext3_get_parent(struct dentry *child);
 static struct export_operations ext3_export_ops = {
-	get_parent: ext3_get_parent,
+	.get_parent = ext3_get_parent,
 };
 
 
@@ -1770,11 +1770,11 @@
 }
 
 static struct file_system_type ext3_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"ext3",
-	get_sb:		ext3_get_sb,
-	kill_sb:	kill_block_super,
-	fs_flags:	FS_REQUIRES_DEV,
+	.owner		= THIS_MODULE,
+	.name		= "ext3",
+	.get_sb		= ext3_get_sb,
+	.kill_sb	= kill_block_super,
+	.fs_flags	= FS_REQUIRES_DEV,
 };
 
 static int __init init_ext3_fs(void)
diff -Nru a/fs/ext3/symlink.c b/fs/ext3/symlink.c
--- a/fs/ext3/symlink.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ext3/symlink.c	Thu Aug  1 14:17:40 2002
@@ -34,6 +34,6 @@
 }
 
 struct inode_operations ext3_fast_symlink_inode_operations = {
-	readlink:	ext3_readlink,		/* BKL not held.  Don't need */
-	follow_link:	ext3_follow_link,	/* BKL not held.  Don't need */
+	.readlink	= ext3_readlink,		/* BKL not held.  Don't need */
+	.follow_link	= ext3_follow_link,	/* BKL not held.  Don't need */
 };
diff -Nru a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
--- a/fs/freevxfs/vxfs_inode.c	Thu Aug  1 14:17:37 2002
+++ b/fs/freevxfs/vxfs_inode.c	Thu Aug  1 14:17:37 2002
@@ -53,6 +53,7 @@
 	.llseek =		generic_file_llseek,
 	.read =			generic_file_read,
 	.mmap =			generic_file_mmap,
+	.sendfile =		generic_file_sendfile,
 };
 
 
diff -Nru a/fs/hpfs/inode.c b/fs/hpfs/inode.c
--- a/fs/hpfs/inode.c	Thu Aug  1 14:17:39 2002
+++ b/fs/hpfs/inode.c	Thu Aug  1 14:17:39 2002
@@ -21,6 +21,7 @@
 	open:		hpfs_open,
 	release:	hpfs_file_release,
 	fsync:		hpfs_file_fsync,
+	sendfile:	generic_file_sendfile,
 };
 
 static struct inode_operations hpfs_file_iops =
diff -Nru a/fs/intermezzo/sysctl.c b/fs/intermezzo/sysctl.c
--- a/fs/intermezzo/sysctl.c	Thu Aug  1 14:17:36 2002
+++ b/fs/intermezzo/sysctl.c	Thu Aug  1 14:17:36 2002
@@ -8,7 +8,6 @@
 #include <linux/time.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
-#include <linux/swapctl.h>
 #include <linux/proc_fs.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff -Nru a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c
--- a/fs/jffs/inode-v23.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs/inode-v23.c	Thu Aug  1 14:17:40 2002
@@ -1631,13 +1631,14 @@
 
 static struct file_operations jffs_file_operations =
 {
-	open:	generic_file_open,
-	llseek:	generic_file_llseek,
-	read:	generic_file_read,
-	write:	generic_file_write,
-	ioctl:	jffs_ioctl,
-	mmap:	generic_file_mmap,
-	fsync:	jffs_fsync,
+	open:		generic_file_open,
+	llseek:		generic_file_llseek,
+	read:		generic_file_read,
+	write:		generic_file_write,
+	ioctl:		jffs_ioctl,
+	mmap:		generic_file_mmap,
+	fsync:		jffs_fsync,
+	sendfile:	generic_file_sendfile,
 };
 
 
diff -Nru a/fs/jffs2/LICENCE b/fs/jffs2/LICENCE
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/fs/jffs2/LICENCE	Thu Aug  1 14:17:41 2002
@@ -0,0 +1,35 @@
+The files in this directory and elsewhere which refer to this LICENCE
+file are part of JFFS2, the Journalling Flash File System v2.
+
+	Copyright (C) 2001, 2002 Red Hat, Inc.
+
+JFFS2 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 or (at your option) any later 
+version.
+
+JFFS2 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 JFFS2; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+As a special exception, if other files instantiate templates or use
+macros or inline functions from these files, or you compile these
+files and link them with other works to produce a work based on these
+files, these files do not by themselves cause the resulting work to be
+covered by the GNU General Public License. However the source code for
+these files must still be made available in accordance with section (3)
+of the GNU General Public License.
+
+This exception does not invalidate any other reasons why a work based on
+this file might be covered by the GNU General Public License.
+
+For information on obtaining alternative licences for JFFS2, see 
+http://sources.redhat.com/jffs2/jffs2-licence.html
+
+
+	$Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $
diff -Nru a/fs/jffs2/TODO b/fs/jffs2/TODO
--- a/fs/jffs2/TODO	Thu Aug  1 14:17:41 2002
+++ b/fs/jffs2/TODO	Thu Aug  1 14:17:41 2002
@@ -1,6 +1,5 @@
-$Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $
+$Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $
 
- - Locking audit. Even more so now 2.5 took away the BKL.
  - disable compression in commit_write()?
  - fine-tune the allocation / GC thresholds
  - chattr support - turning on/off and tuning compression per-inode
@@ -9,7 +8,6 @@
 	mount doesn't have to read the flash twice for large files.
 	Make this a per-inode option, changable with chattr, so you can
 	decide which inodes should be in-core immediately after mount.
- - stop it depending on a block device.
  - test, test, test
 
  - NAND flash support:
@@ -22,3 +20,25 @@
 	- timed flush of old wbuf
 	- fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead.
 
+
+ - Optimisations:
+   - Stop GC from decompressing and immediately recompressing nodes which could
+     just be copied intact.
+   - Furthermore, in the case where it could be copied intact we don't even need
+     to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag
+     to show a node can be copied intact and it's _not_ in icache, we could just do
+     it, fix up the next_in_ino list and move on. We would need a way to find out
+     _whether_ it's in icache though -- if it's in icache we also need to do the 
+     fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could
+     help.
+   - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in 
+     the full dirent, we only need to go to the flash in lookup() when we think we've
+     got a match, and in readdir(). 
+   - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately?
+   - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into
+	jffs2_mark_node_obsolete(). Can all callers work it out?
+   - Don't check data CRC on node scan during mount. We don't really need to know 
+	yet. This means we can't build up node fragment lists, and hence can't 
+	build accurate clean/dirty information. But we don't _need_ that for reading,
+	only for writing. And in fact we don't even need it for writing until we 
+	start to need GC.
diff -Nru a/fs/jffs2/background.c b/fs/jffs2/background.c
--- a/fs/jffs2/background.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/background.c	Thu Aug  1 14:17:36 2002
@@ -5,45 +5,21 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: background.c,v 1.23 2002/03/06 12:37:08 dwmw2 Exp $
+ * $Id: background.c,v 1.29 2002/06/07 10:04:28 dwmw2 Exp $
  *
  */
 
 #define __KERNEL_SYSCALLS__
 
 #include <linux/kernel.h>
-#include <linux/unistd.h>
 #include <linux/jffs2.h>
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
 #include <linux/completion.h>
 #include <linux/mtd/compatmac.h> /* recalc_sigpending() */
+#include <linux/unistd.h>
 #include "nodelist.h"
 
 
@@ -86,6 +62,13 @@
 
 void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
 {
+	if (c->mtd->type == MTD_NANDFLASH) {
+		/* stop a eventually scheduled wbuf flush timer */
+		del_timer_sync(&c->wbuf_timer);
+		/* make sure, that a scheduled wbuf flush task is completed */
+		flush_scheduled_tasks();
+	}
+
 	spin_lock_bh(&c->erase_completion_lock);
 	if (c->gc_task) {
 		D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid));
@@ -171,11 +154,23 @@
 
 static int thread_should_wake(struct jffs2_sb_info *c)
 {
-	D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x\n", 
-		  c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size));
+	uint32_t gcnodeofs = 0;
+	int ret;
+
+	/* Don't count any progress we've already made through the gcblock
+	   as dirty space, for the purposes of this calculation */
+	if (c->gcblock && c->gcblock->gc_node)
+		gcnodeofs = c->gcblock->gc_node->flash_offset & ~3 & (c->sector_size-1);
+
 	if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER &&
-	    c->dirty_size > c->sector_size)
-		return 1;
+	    (c->dirty_size - gcnodeofs) > c->sector_size)
+		ret = 1;
 	else 
-		return 0;
+		ret = 0;
+
+	D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x (mod 0x%x): %s\n", 
+		  c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size,
+		  c->dirty_size - gcnodeofs, ret?"yes":"no"));
+
+	return ret;
 }
diff -Nru a/fs/jffs2/build.c b/fs/jffs2/build.c
--- a/fs/jffs2/build.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/build.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: build.c,v 1.32 2002/03/08 15:11:24 dwmw2 Exp $
+ * $Id: build.c,v 1.35 2002/05/20 14:56:37 dwmw2 Exp $
  *
  */
 
@@ -124,6 +100,9 @@
 	}
 	D1(printk(KERN_DEBUG "Pass 3 complete\n"));
 
+	/* Rotate the lists by some number to ensure wear levelling */
+	jffs2_rotate_lists(c);
+
 	return ret;
 }
 	
@@ -304,6 +283,7 @@
 	spin_lock_init(&c->inocache_lock);
 
 	INIT_LIST_HEAD(&c->clean_list);
+	INIT_LIST_HEAD(&c->very_dirty_list);
 	INIT_LIST_HEAD(&c->dirty_list);
 	INIT_LIST_HEAD(&c->erasable_list);
 	INIT_LIST_HEAD(&c->erasing_list);
diff -Nru a/fs/jffs2/compr.c b/fs/jffs2/compr.c
--- a/fs/jffs2/compr.c	Thu Aug  1 14:17:39 2002
+++ b/fs/jffs2/compr.c	Thu Aug  1 14:17:39 2002
@@ -5,33 +5,9 @@
  *
  * Created by Arjan van de Ven <arjanv@redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: compr.c,v 1.23 2002/01/25 01:49:26 dwmw2 Exp $
+ * $Id: compr.c,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
--- a/fs/jffs2/compr_rtime.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/compr_rtime.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by Arjan van de Ven <arjanv@redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: compr_rtime.c,v 1.8 2002/01/25 01:49:26 dwmw2 Exp $
+ * $Id: compr_rtime.c,v 1.9 2002/05/20 14:56:37 dwmw2 Exp $
  *
  *
  * Very simple lz77-ish encoder.
diff -Nru a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
--- a/fs/jffs2/compr_rubin.c	Thu Aug  1 14:17:41 2002
+++ b/fs/jffs2/compr_rubin.c	Thu Aug  1 14:17:41 2002
@@ -5,33 +5,9 @@
  *
  * Created by Arjan van de Ven <arjanv@redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: compr_rubin.c,v 1.16 2002/01/25 01:49:26 dwmw2 Exp $
+ * $Id: compr_rubin.c,v 1.17 2002/05/20 14:56:37 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c
--- a/fs/jffs2/compr_zlib.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/compr_zlib.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: compr_zlib.c,v 1.15 2002/03/04 09:35:48 dwmw2 Exp $
+ * $Id: compr_zlib.c,v 1.18 2002/05/20 14:56:37 dwmw2 Exp $
  *
  */
 
@@ -65,21 +41,21 @@
 {
 	deflate_workspace = vmalloc(zlib_deflate_workspacesize());
 	if (!deflate_workspace) {
-		printk("Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize());
+		printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize());
 		return -ENOMEM;
 	}
-	D1(printk("Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize()));
+	D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize()));
 	inflate_workspace = vmalloc(zlib_inflate_workspacesize());
 	if (!inflate_workspace) {
-		printk("Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize());
+		printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize());
 		vfree(deflate_workspace);
 		return -ENOMEM;
 	}
-	D1(printk("Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize()));
+	D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize()));
 	return 0;
 }
 
-void __exit jffs2_zlib_exit(void)
+void jffs2_zlib_exit(void)
 {
 	vfree(deflate_workspace);
 	vfree(inflate_workspace);
diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c
--- a/fs/jffs2/dir.c	Thu Aug  1 14:17:39 2002
+++ b/fs/jffs2/dir.c	Thu Aug  1 14:17:39 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: dir.c,v 1.68 2002/03/11 12:36:59 dwmw2 Exp $
+ * $Id: dir.c,v 1.71 2002/07/23 17:00:45 dwmw2 Exp $
  *
  */
 
@@ -45,7 +21,6 @@
 #include <linux/jffs2_fs_i.h>
 #include <linux/jffs2_fs_sb.h>
 #include <linux/time.h>
-#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 static int jffs2_readdir (struct file *, void *, filldir_t);
@@ -63,25 +38,25 @@
 
 struct file_operations jffs2_dir_operations =
 {
-	read:		generic_read_dir,
-	readdir:	jffs2_readdir,
-	ioctl:		jffs2_ioctl,
-	fsync:		jffs2_fsync
+	.read =		generic_read_dir,
+	.readdir =	jffs2_readdir,
+	.ioctl =	jffs2_ioctl,
+	.fsync =	jffs2_fsync
 };
 
 
 struct inode_operations jffs2_dir_inode_operations =
 {
-	create:		jffs2_create,
-	lookup:		jffs2_lookup,
-	link:		jffs2_link,
-	unlink:		jffs2_unlink,
-	symlink:	jffs2_symlink,
-	mkdir:		jffs2_mkdir,
-	rmdir:		jffs2_rmdir,
-	mknod:		jffs2_mknod,
-	rename:		jffs2_rename,
-	setattr:	jffs2_setattr,
+	.create =	jffs2_create,
+	.lookup =	jffs2_lookup,
+	.link =		jffs2_link,
+	.unlink =	jffs2_unlink,
+	.symlink =	jffs2_symlink,
+	.mkdir =	jffs2_mkdir,
+	.rmdir =	jffs2_rmdir,
+	.mknod =	jffs2_mknod,
+	.rename =	jffs2_rename,
+	.setattr =	jffs2_setattr,
 };
 
 /***********************************************************************/
@@ -144,8 +119,6 @@
 
 	D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino));
 
-	lock_kernel();
-
 	f = JFFS2_INODE_INFO(inode);
 	c = JFFS2_SB_INFO(inode->i_sb);
 
@@ -189,7 +162,6 @@
 	up(&f->sem);
  out:
 	filp->f_pos = offset;
-	unlock_kernel();
 	return 0;
 }
 
@@ -744,8 +716,30 @@
 {
 	int ret;
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
+	struct jffs2_inode_info *victim_f = NULL;
 	uint8_t type;
 
+	/* The VFS will check for us and prevent trying to rename a 
+	 * file over a directory and vice versa, but if it's a directory,
+	 * the VFS can't check whether the victim is empty. The filesystem
+	 * needs to do that for itself.
+	 */
+	if (new_dentry->d_inode) {
+		victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
+		if (S_ISDIR(new_dentry->d_inode->i_mode)) {
+			struct jffs2_full_dirent *fd;
+
+			down(&victim_f->sem);
+			for (fd = victim_f->dents; fd; fd = fd->next) {
+				if (fd->ino) {
+					up(&victim_f->sem);
+					return -ENOTEMPTY;
+				}
+			}
+			up(&victim_f->sem);
+		}
+	}
+
 	/* XXX: We probably ought to alloc enough space for
 	   both nodes at the same time. Writing the new link, 
 	   then getting -ENOSPC, is quite bad :)
@@ -764,7 +758,21 @@
 	if (ret)
 		return ret;
 
-	if (S_ISDIR(old_dentry->d_inode->i_mode))
+	if (victim_f) {
+		/* There was a victim. Kill it off nicely */
+		new_dentry->d_inode->i_nlink--;
+		/* Don't oops if the victim was a dirent pointing to an
+		   inode which didn't exist. */
+		if (victim_f->inocache) {
+			down(&victim_f->sem);
+			victim_f->inocache->nlink--;
+			up(&victim_f->sem);
+		}
+	}
+
+	/* If it was a directory we moved, and there was no victim, 
+	   increase i_nlink on its new parent */
+	if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f)
 		new_dir_i->i_nlink++;
 
 	/* Unlink the original */
diff -Nru a/fs/jffs2/erase.c b/fs/jffs2/erase.c
--- a/fs/jffs2/erase.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/erase.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: erase.c,v 1.35 2002/03/08 15:11:24 dwmw2 Exp $
+ * $Id: erase.c,v 1.39 2002/07/23 17:00:45 dwmw2 Exp $
  *
  */
 
@@ -286,20 +262,12 @@
 
 void jffs2_mark_erased_blocks(struct jffs2_sb_info *c)
 {
-	static struct jffs2_unknown_node marker = {
-		magic:		JFFS2_MAGIC_BITMASK,
-		nodetype:	JFFS2_NODETYPE_CLEANMARKER,
-		totlen:		sizeof(struct jffs2_unknown_node)
-	};
 	struct jffs2_eraseblock *jeb;
 	struct jffs2_raw_node_ref *marker_ref = NULL;
 	unsigned char *ebuf;
 	size_t retlen;
 	int ret;
 
-	if (unlikely(!marker.hdr_crc))
-		marker.hdr_crc = crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4);
-
 	spin_lock_bh(&c->erase_completion_lock);
 	while (!list_empty(&c->erase_complete_list)) {
 		jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
@@ -359,6 +327,7 @@
 					}
 				}
 				ofs += readlen;
+				cond_resched();
 			}
 			kfree(ebuf);
 		}
@@ -376,22 +345,30 @@
 			jeb->used_size = 0;
 			jeb->dirty_size = 0;
 		} else {
-			ret = jffs2_flash_write(c, jeb->offset, sizeof(marker), &retlen, (char *)&marker);
+			struct jffs2_unknown_node marker = {
+				.magic =	JFFS2_MAGIC_BITMASK,
+				.nodetype =	JFFS2_NODETYPE_CLEANMARKER,
+				.totlen =	c->cleanmarker_size
+			};
+
+			marker.hdr_crc = crc32(0, &marker, marker.totlen - 4);
+
+			ret = jffs2_flash_write(c, jeb->offset, marker.totlen, &retlen, (char *)&marker);
 			if (ret) {
 				printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n",
 				       jeb->offset, ret);
 				goto bad2;
 			}
-			if (retlen != sizeof(marker)) {
+			if (retlen != marker.totlen) {
 				printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n",
-				       jeb->offset, sizeof(marker), retlen);
+				       jeb->offset, marker.totlen, retlen);
 				goto bad2;
 			}
 			
 			marker_ref->next_in_ino = NULL;
 			marker_ref->next_phys = NULL;
 			marker_ref->flash_offset = jeb->offset;
-			marker_ref->totlen = PAD(sizeof(marker));
+			marker_ref->totlen = PAD(marker.totlen);
 			
 			jeb->first_node = jeb->last_node = marker_ref;
 			
diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c
--- a/fs/jffs2/file.c	Thu Aug  1 14:17:41 2002
+++ b/fs/jffs2/file.c	Thu Aug  1 14:17:41 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: file.c,v 1.70 2002/03/05 09:55:07 dwmw2 Exp $
+ * $Id: file.c,v 1.76 2002/07/29 08:25:35 dwmw2 Exp $
  *
  */
 
@@ -43,7 +19,6 @@
 #include <linux/pagemap.h>
 #include <linux/crc32.h>
 #include <linux/jffs2.h>
-#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
@@ -66,36 +41,41 @@
 	 * maybe we have to think about it to find a smarter
 	 * solution.
 	 */
+	down(&c->alloc_sem);
 	down(&f->sem);
 	jffs2_flush_wbuf(c,2);
 	up(&f->sem);
+	up(&c->alloc_sem);
 			
 	return 0;	
 }
 
 struct file_operations jffs2_file_operations =
 {
-	llseek:		generic_file_llseek,
-	open:		generic_file_open,
-	read:		generic_file_read,
-	write:		generic_file_write,
-	ioctl:		jffs2_ioctl,
-	mmap:		generic_file_mmap,
-	fsync:		jffs2_fsync
+	.llseek =	generic_file_llseek,
+	.open =		generic_file_open,
+	.read =		generic_file_read,
+	.write =	generic_file_write,
+	.ioctl =	jffs2_ioctl,
+	.mmap =		generic_file_mmap,
+	.fsync =	jffs2_fsync,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,29)
+	.sendfile =	generic_file_sendfile
+#endif
 };
 
 /* jffs2_file_inode_operations */
 
 struct inode_operations jffs2_file_inode_operations =
 {
-	setattr:	jffs2_setattr
+	.setattr =	jffs2_setattr
 };
 
 struct address_space_operations jffs2_file_address_operations =
 {
-	readpage:	jffs2_readpage,
-	prepare_write:	jffs2_prepare_write,
-	commit_write:	jffs2_commit_write
+	.readpage =	jffs2_readpage,
+	.prepare_write =jffs2_prepare_write,
+	.commit_write =	jffs2_commit_write
 };
 
 int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
@@ -110,12 +90,11 @@
 	int mdatalen = 0;
 	unsigned int ivalid;
 	uint32_t phys_ofs, alloclen;
-	int ret = 0;
-	lock_kernel();
+	int ret;
 	D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
 	ret = inode_change_ok(inode, iattr);
 	if (ret) 
-		goto out;
+		return ret;
 
 	/* Special cases - we don't want more than one data node
 	   for these types on the medium at any time. So setattr
@@ -132,14 +111,12 @@
 	} else if (S_ISLNK(inode->i_mode)) {
 		mdatalen = f->metadata->size;
 		mdata = kmalloc(f->metadata->size, GFP_USER);
-		if (!mdata) {
-			ret = -ENOMEM;
-			goto out;
-		}
+		if (!mdata)
+			return -ENOMEM;
 		ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen);
 		if (ret) {
 			kfree(mdata);
-			goto out;
+			return ret;
 		}
 		D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
 	}
@@ -148,8 +125,7 @@
 	if (!ri) {
 		if (S_ISLNK(inode->i_mode))
 			kfree(mdata);
-		ret = -ENOMEM;
-		goto out;
+		return -ENOMEM;
 	}
 		
 	ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL);
@@ -157,7 +133,7 @@
 		jffs2_free_raw_inode(ri);
 		if (S_ISLNK(inode->i_mode & S_IFMT))
 			 kfree(mdata);
-		goto out;
+		return ret;
 	}
 	down(&f->sem);
 	ivalid = iattr->ia_valid;
@@ -206,8 +182,7 @@
 		jffs2_complete_reservation(c);
 		jffs2_free_raw_inode(ri);
 		up(&f->sem);
-		ret = PTR_ERR(new_metadata);
-		goto out;
+		return PTR_ERR(new_metadata);
 	}
 	/* It worked. Update the inode */
 	inode->i_atime = ri->atime;
@@ -241,9 +216,7 @@
 	up(&f->sem);
 	jffs2_complete_reservation(c);
 
-out:
-	unlock_kernel();	
-	return ret;
+	return 0;
 }
 
 int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
@@ -288,18 +261,18 @@
 
 int jffs2_readpage (struct file *filp, struct page *pg)
 {
-	struct jffs2_inode_info *f = JFFS2_INODE_INFO(filp->f_dentry->d_inode);
+	struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
 	int ret;
 	
 	down(&f->sem);
-	ret = jffs2_do_readpage_unlock(filp->f_dentry->d_inode, pg);
+	ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
 	up(&f->sem);
 	return ret;
 }
 
 int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, unsigned end)
 {
-	struct inode *inode = filp->f_dentry->d_inode;
+	struct inode *inode = pg->mapping->host;
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
 	uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT;
 	int ret = 0;
@@ -383,7 +356,7 @@
 	/* Actually commit the write from the page cache page we're looking at.
 	 * For now, we write the full page out each time. It sucks, but it's simple
 	 */
-	struct inode *inode = filp->f_dentry->d_inode;
+	struct inode *inode = pg->mapping->host;
 	struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
 	struct jffs2_raw_inode *ri;
diff -Nru a/fs/jffs2/fs.c b/fs/jffs2/fs.c
--- a/fs/jffs2/fs.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/fs.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: fs.c,v 1.4 2002/03/11 12:36:59 dwmw2 Exp $
+ * $Id: fs.c,v 1.13 2002/07/02 22:48:24 dwmw2 Exp $
  *
  */
 
@@ -44,7 +20,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/pagemap.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include "nodelist.h"
 
 int jffs2_statfs(struct super_block *sb, struct statfs *buf)
@@ -69,122 +44,10 @@
 
 	buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT;
 
-#if CONFIG_JFFS2_FS_DEBUG > 0
-	printk(KERN_DEBUG "STATFS:\n");
-	printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size);
-	printk(KERN_DEBUG "used_size: %08x\n", c->used_size);
-	printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size);
-	printk(KERN_DEBUG "free_size: %08x\n", c->free_size);
-	printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size);
-	printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size);
-	printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size);
-	printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE);
-
-	if (c->nextblock) {
-		printk(KERN_DEBUG "nextblock: 0x%08x\n", c->nextblock->offset);
-	} else {
-		printk(KERN_DEBUG "nextblock: NULL\n");
-	}
-	if (c->gcblock) {
-		printk(KERN_DEBUG "gcblock: 0x%08x\n", c->gcblock->offset);
-	} else {
-		printk(KERN_DEBUG "gcblock: NULL\n");
-	}
-	if (list_empty(&c->clean_list)) {
-		printk(KERN_DEBUG "clean_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->clean_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "clean_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->dirty_list)) {
-		printk(KERN_DEBUG "dirty_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->dirty_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "dirty_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->erasable_list)) {
-		printk(KERN_DEBUG "erasable_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->erasable_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erasable_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->erasing_list)) {
-		printk(KERN_DEBUG "erasing_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->erasing_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erasing_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->erase_pending_list)) {
-		printk(KERN_DEBUG "erase_pending_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->erase_pending_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erase_pending_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->erasable_pending_wbuf_list)) {
-		printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->erasable_pending_wbuf_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "erase_pending_wbuf_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->free_list)) {
-		printk(KERN_DEBUG "free_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->free_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "free_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->bad_list)) {
-		printk(KERN_DEBUG "bad_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->bad_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "bad_list: %08x\n", jeb->offset);
-		}
-	}
-	if (list_empty(&c->bad_used_list)) {
-		printk(KERN_DEBUG "bad_used_list: empty\n");
-	} else {
-		struct list_head *this;
-
-		list_for_each(this, &c->bad_used_list) {
-			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
-			printk(KERN_DEBUG "bad_used_list: %08x\n", jeb->offset);
-		}
-	}
-#endif /* CONFIG_JFFS2_FS_DEBUG */
+	D1(jffs2_dump_block_lists(c));
 
 	spin_unlock_bh(&c->erase_completion_lock);
 
-
 	return 0;
 }
 
@@ -275,9 +138,9 @@
 		if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
 			/* Eep */
 			printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
+			up(&f->sem);
 			jffs2_do_clear_inode(c, f);
 			make_bad_inode(inode);
-			up(&f->sem);
 			return;
 		}			
 
@@ -321,21 +184,24 @@
 void jffs2_write_super (struct super_block *sb)
 {
 	struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
-
-	lock_kernel();
 	sb->s_dirt = 0;
 
-	if (sb->s_flags & MS_RDONLY) {
-		unlock_kernel();	
+	if (sb->s_flags & MS_RDONLY)
 		return;
-	}
 
-	D1(printk("jffs2_write_super(): flush_wbuf before gc-trigger\n"));
-	jffs2_flush_wbuf(c, 2);
+	D1(printk(KERN_DEBUG "jffs2_write_super(): flush_wbuf before gc-trigger\n"));
 	jffs2_garbage_collect_trigger(c);
 	jffs2_erase_pending_blocks(c);
 	jffs2_mark_erased_blocks(c);
-	unlock_kernel();
+	/* Eep. If we lock this here, we deadlock with jffs2_reserve_space() when
+	 * it locks the alloc_sem and jffs2_do_reserve_space() waits for erases
+	 * to happen. I think the erases and/or the flush_wbuf want doing from
+	 *
+	 */
+	if (!down_trylock(&c->alloc_sem)) {
+		jffs2_flush_wbuf(c, 2);
+		up(&c->alloc_sem);
+	} // else it stays dirty. FIXME.
 }
 
 
@@ -400,33 +266,61 @@
 {
 	struct jffs2_sb_info *c;
 	struct inode *root_i;
+	int ret;
 
 	c = JFFS2_SB_INFO(sb);
 
 	c->sector_size = c->mtd->erasesize;
 	c->flash_size = c->mtd->size;
 
+#if 0
 	if (c->sector_size < 0x10000) {
 		printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using 64KiB instead\n",
 		       c->sector_size / 1024);
 		c->sector_size = 0x10000;
 	}
+#endif
 	if (c->flash_size < 5*c->sector_size) {
 		printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n",
 		       c->flash_size / c->sector_size);
 		return -EINVAL;
 	}
+
+	c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
+	/* Jörn -- stick alignment for weird 8-byte-page flash here */
+
+	if (jffs2_cleanmarker_oob(c)) {
+		/* Cleanmarker is out-of-band, so inline size zero */
+		c->cleanmarker_size = 0;
+	}
+
 	if (c->mtd->type == MTD_NANDFLASH) {
 		/* Initialise write buffer */
 		c->wbuf_pagesize = c->mtd->oobblock;
 		c->wbuf_ofs = 0xFFFFFFFF;
 		c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
 		if (!c->wbuf)
-			goto out_mtd;
+			return -ENOMEM;
+
+		/* Initialize process for timed wbuf flush */
+		INIT_TQUEUE(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c);
+		/* Initialize timer for timed wbuf flush */
+		init_timer(&c->wbuf_timer);
+		c->wbuf_timer.function = jffs2_wbuf_timeout;
+		c->wbuf_timer.data = (unsigned long) c;
 	}
 
-	if (jffs2_do_mount_fs(c))
-		goto out_mtd;
+	c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
+	if (!c->inocache_list) {
+		ret = -ENOMEM;
+		goto out_wbuf;
+	}
+	memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
+
+	if ((ret = jffs2_do_mount_fs(c)))
+		goto out_inohash;
+
+	ret = -EINVAL;
 
 	D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n"));
 	root_i = iget(sb, 1);
@@ -456,6 +350,10 @@
 	jffs2_free_ino_caches(c);
 	jffs2_free_raw_node_refs(c);
 	kfree(c->blocks);
- out_mtd:
-	return -EINVAL;
+ out_inohash:
+	kfree(c->inocache_list);
+ out_wbuf:
+	if (c->wbuf)
+		kfree(c->wbuf);
+	return ret;
 }
diff -Nru a/fs/jffs2/gc.c b/fs/jffs2/gc.c
--- a/fs/jffs2/gc.c	Thu Aug  1 14:17:39 2002
+++ b/fs/jffs2/gc.c	Thu Aug  1 14:17:39 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: gc.c,v 1.68 2002/03/08 15:11:24 dwmw2 Exp $
+ * $Id: gc.c,v 1.74 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
@@ -65,14 +41,21 @@
 
 	/* Pick an eraseblock to garbage collect next. This is where we'll
 	   put the clever wear-levelling algorithms. Eventually.  */
+	/* We possibly want to favour the dirtier blocks more when the
+	   number of free blocks is low. */
 	if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) {
 		D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n"));
 		nextlist = &c->bad_used_list;
-	} else if (n < 100 && !list_empty(&c->erasable_list)) {
+	} else if (n < 50 && !list_empty(&c->erasable_list)) {
+		/* Note that most of them will have gone directly to be erased. 
+		   So don't favour the erasable_list _too_ much. */
 		D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n"));
 		nextlist = &c->erasable_list;
+	} else if (n < 110 && !list_empty(&c->very_dirty_list)) {
+		/* Most of the time, pick one off the very_dirty list */
+		D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n"));
+		nextlist = &c->very_dirty_list;
 	} else if (n < 126 && !list_empty(&c->dirty_list)) {
-		/* Most of the time, pick one off the dirty list */
 		D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n"));
 		nextlist = &c->dirty_list;
 	} else if (!list_empty(&c->clean_list)) {
@@ -82,12 +65,15 @@
 		D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n"));
 
 		nextlist = &c->dirty_list;
+	} else if (!list_empty(&c->very_dirty_list)) {
+		D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n"));
+		nextlist = &c->very_dirty_list;
 	} else if (!list_empty(&c->erasable_list)) {
-		D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and dirty_list were empty)\n"));
+		D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n"));
 
 		nextlist = &c->erasable_list;
 	} else {
-		/* Eep. Both were empty */
+		/* Eep. All were empty */
 		printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n");
 		return NULL;
 	}
@@ -100,6 +86,8 @@
 		printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset);
 		BUG();
 	}
+
+	D1(jffs2_dump_block_lists(c));
 	return ret;
 }
 
@@ -138,7 +126,9 @@
 		return -EIO;
 	}
 
-	D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset));
+	D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size));
+	D1(if (c->nextblock)
+	   printk(KERN_DEBUG "Nextblock at  %08x, used_size %08x, dirty_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size));
 
 	if (!jeb->used_size)
 		goto eraseit;
@@ -606,9 +596,21 @@
 			jffs2_mark_node_obsolete(c, f->metadata->raw);
 			jffs2_free_full_dnode(f->metadata);
 			f->metadata = NULL;
-			return 0;
 		}
+		return 0;
 	}
+
+	/* 
+	 * We should only get here in the case where the node we are
+	 * replacing had more than one frag, so we kept the same version
+	 * number as before. (Except in case of error -- see 'goto fill;' 
+	 * above.)
+	 */
+	D1(if(unlikely(fn->frags <= 1)) {
+		printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n",
+		       fn->frags, ri.version, f->highest_version, ri.ino);
+	});
+
 	for (frag = f->fraglist; frag; frag = frag->next) {
 		if (frag->ofs > fn->size + fn->ofs)
 			break;
@@ -760,7 +762,7 @@
 
 	kunmap(pg);
 	/* XXX: Does the page get freed automatically? */
-	/* AAA: Judging by the unmount getting stuck in __wait_on_page_locked, nope. */
+	/* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */
 	page_cache_release(pg);
 	return ret;
 }
diff -Nru a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c
--- a/fs/jffs2/ioctl.c	Thu Aug  1 14:17:41 2002
+++ b/fs/jffs2/ioctl.c	Thu Aug  1 14:17:41 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: ioctl.c,v 1.5 2001/03/15 15:38:24 dwmw2 Exp $
+ * $Id: ioctl.c,v 1.6 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c
--- a/fs/jffs2/malloc.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/malloc.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: malloc.c,v 1.21 2002/03/12 17:36:55 dwmw2 Exp $
+ * $Id: malloc.c,v 1.22 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c
--- a/fs/jffs2/nodelist.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/nodelist.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: nodelist.c,v 1.42 2002/03/11 11:17:29 dwmw2 Exp $
+ * $Id: nodelist.c,v 1.47 2002/06/26 01:25:30 dwmw2 Exp $
  *
  */
 
@@ -69,7 +45,7 @@
 	*prev = new;
 
  out:
-	D1(while(*list) {
+	D2(while(*list) {
 		printk(KERN_DEBUG "Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list)->name, (*list)->nhash, (*list)->ino);
 		list = &(*list)->next;
 	});
@@ -311,17 +287,14 @@
 	D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino));
 	spin_lock (&c->inocache_lock);
 
-	if (c->inocache_last && c->inocache_last->ino == ino) {
-		ret = c->inocache_last;
-	} else {
-		ret = c->inocache_list[ino % INOCACHE_HASHSIZE];
-		while (ret && ret->ino < ino) {
-			ret = ret->next;
-		}
-
-		if (ret && ret->ino != ino)
-			ret = NULL;
+	ret = c->inocache_list[ino % INOCACHE_HASHSIZE];
+	while (ret && ret->ino < ino) {
+		ret = ret->next;
 	}
+	
+	if (ret && ret->ino != ino)
+		ret = NULL;
+
 	spin_unlock(&c->inocache_lock);
 
 	D2(printk(KERN_DEBUG "jffs2_get_ino_cache found %p for ino %u\n", ret, ino));
@@ -342,8 +315,6 @@
 	new->next = *prev;
 	*prev = new;
 
-	c->inocache_last = new;
-
 	spin_unlock(&c->inocache_lock);
 }
 
@@ -361,8 +332,6 @@
 	if ((*prev) == old) {
 		*prev = old->next;
 	}
-	if (c->inocache_last == old)
-		c->inocache_last = NULL;
 
 	spin_unlock(&c->inocache_lock);
 }
@@ -382,7 +351,6 @@
 		}
 		c->inocache_list[i] = NULL;
 	}
-	c->inocache_last = NULL;
 }
 
 void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
diff -Nru a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
--- a/fs/jffs2/nodelist.h	Thu Aug  1 14:17:41 2002
+++ b/fs/jffs2/nodelist.h	Thu Aug  1 14:17:41 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: nodelist.h,v 1.68 2002/03/08 11:27:19 dwmw2 Exp $
+ * $Id: nodelist.h,v 1.74 2002/06/26 01:20:43 dwmw2 Exp $
  *
  */
 
@@ -117,6 +93,8 @@
 	int nlink;
 };
 
+#define INOCACHE_HASHSIZE 128
+
 struct jffs2_scan_info {
 	struct jffs2_full_dirent *dents;
 	struct jffs2_tmp_dnode_info *tmpnodes;
@@ -172,7 +150,6 @@
 	struct jffs2_full_dnode *node; /* NULL for holes */
 	uint32_t size;
 	uint32_t ofs; /* Don't really need this, but optimisation */
-	uint32_t node_ofs; /* offset within the physical node */
 };
 
 struct jffs2_eraseblock
@@ -240,6 +217,9 @@
 #define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE)		/* ... merge pages when garbage collecting */
 
 
+/* How much dirty space before it goes on the very_dirty_list */
+#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2))
+
 #define PAD(x) (((x)+3)&~3)
 
 static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw)
@@ -271,6 +251,7 @@
 int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty);
 void jffs2_complete_reservation(struct jffs2_sb_info *c);
 void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
+void jffs2_dump_block_lists(struct jffs2_sb_info *c);
 
 /* write.c */
 int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
@@ -331,6 +312,7 @@
 
 /* scan.c */
 int jffs2_scan_medium(struct jffs2_sb_info *c);
+void jffs2_rotate_lists(struct jffs2_sb_info *c);
 
 /* build.c */
 int jffs2_do_mount_fs(struct jffs2_sb_info *c);
diff -Nru a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
--- a/fs/jffs2/nodemgmt.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/nodemgmt.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: nodemgmt.c,v 1.63 2002/03/08 14:54:09 dwmw2 Exp $
+ * $Id: nodemgmt.c,v 1.70 2002/07/02 22:48:24 dwmw2 Exp $
  *
  */
 
@@ -158,9 +134,15 @@
 		c->free_size -= jeb->free_size;
 		jeb->dirty_size += jeb->free_size;
 		jeb->free_size = 0;
-		D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
+		if (VERYDIRTY(c, jeb->dirty_size)) {
+			D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
 			  jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));
-		list_add_tail(&jeb->list, &c->dirty_list);
+			list_add_tail(&jeb->list, &c->very_dirty_list);
+		} else {
+			D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
+			  jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));
+			list_add_tail(&jeb->list, &c->dirty_list);
+		}
 		c->nextblock = jeb = NULL;
 	}
 	
@@ -180,6 +162,7 @@
 				list_del(&ejeb->list);
 				list_add_tail(&ejeb->list, &c->erase_pending_list);
 				c->nr_erasing_blocks++;
+				jffs2_erase_pending_trigger(c);
 				D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n",
 					  ejeb->offset));
 			}
@@ -232,10 +215,7 @@
 		c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list);
 		c->nr_free_blocks--;
 
-		/* On NAND free_size == sector_size, cleanmarker is in spare area !*/
-		if (jeb->free_size != c->sector_size - 
-			(jffs2_cleanmarker_oob(c)) ? 0 : sizeof(struct jffs2_unknown_node)) {
-
+		if (jeb->free_size != c->sector_size - c->cleanmarker_size) {
 			printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size);
 			goto restart;
 		}
@@ -420,8 +400,19 @@
 				BUG();
 			}
 		} else {
-			D1(printk(KERN_DEBUG "...and adding to erasable_list\n"));
-			list_add_tail(&jeb->list, &c->erasable_list);
+			if (jiffies & 127) {
+				/* Most of the time, we just erase it immediately. Otherwise we
+				   spend ages scanning it on mount, etc. */
+				D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n"));
+				list_add_tail(&jeb->list, &c->erase_pending_list);
+				c->nr_erasing_blocks++;
+				jffs2_erase_pending_trigger(c);
+			} else {
+				/* Sometimes, however, we leave it elsewhere so it doesn't get
+				   immediately reused, and we spread the load a bit. */
+				D1(printk(KERN_DEBUG "...and adding to erasable_list\n"));
+				list_add_tail(&jeb->list, &c->erasable_list);
+			}				
 		}
 		D1(printk(KERN_DEBUG "Done OK\n"));
 	} else if (jeb == c->gcblock) {
@@ -431,6 +422,12 @@
 		list_del(&jeb->list);
 		D1(printk(KERN_DEBUG "...and adding to dirty_list\n"));
 		list_add_tail(&jeb->list, &c->dirty_list);
+	} else if (VERYDIRTY(c, jeb->dirty_size) &&
+		   !VERYDIRTY(c, jeb->dirty_size - ref->totlen)) {
+		D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset));
+		list_del(&jeb->list);
+		D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n"));
+		list_add_tail(&jeb->list, &c->very_dirty_list);
 	}
 
 	spin_unlock_bh(&c->erase_completion_lock);
@@ -469,3 +466,129 @@
 		return;
 	}
 }
+
+#if CONFIG_JFFS2_FS_DEBUG > 0
+void jffs2_dump_block_lists(struct jffs2_sb_info *c)
+{
+	printk(KERN_DEBUG "jffs2_dump_block_lists:\n");
+	printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size);
+	printk(KERN_DEBUG "used_size: %08x\n", c->used_size);
+	printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size);
+	printk(KERN_DEBUG "free_size: %08x\n", c->free_size);
+	printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size);
+	printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size);
+	printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size);
+	printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE);
+
+	if (c->nextblock) {
+		printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size);
+	} else {
+		printk(KERN_DEBUG "nextblock: NULL\n");
+	}
+	if (c->gcblock) {
+		printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->free_size);
+	} else {
+		printk(KERN_DEBUG "gcblock: NULL\n");
+	}
+	if (list_empty(&c->clean_list)) {
+		printk(KERN_DEBUG "clean_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->clean_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->very_dirty_list)) {
+		printk(KERN_DEBUG "very_dirty_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->very_dirty_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->dirty_list)) {
+		printk(KERN_DEBUG "dirty_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->dirty_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->erasable_list)) {
+		printk(KERN_DEBUG "erasable_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->erasable_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->erasing_list)) {
+		printk(KERN_DEBUG "erasing_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->erasing_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->erase_pending_list)) {
+		printk(KERN_DEBUG "erase_pending_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->erase_pending_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->erasable_pending_wbuf_list)) {
+		printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->erasable_pending_wbuf_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->free_list)) {
+		printk(KERN_DEBUG "free_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->free_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->bad_list)) {
+		printk(KERN_DEBUG "bad_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->bad_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+	if (list_empty(&c->bad_used_list)) {
+		printk(KERN_DEBUG "bad_used_list: empty\n");
+	} else {
+		struct list_head *this;
+
+		list_for_each(this, &c->bad_used_list) {
+			struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+			printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
+		}
+	}
+}
+#endif /* CONFIG_JFFS2_FS_DEBUG */
diff -Nru a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
--- a/fs/jffs2/os-linux.h	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/os-linux.h	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: os-linux.h,v 1.16 2002/03/17 10:18:42 dwmw2 Exp $
+ * $Id: os-linux.h,v 1.19 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
@@ -101,6 +77,8 @@
 #define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0)
 #define jffs2_write_nand_badblock(c,jeb) do { ; } while(0)
 #define jffs2_flash_writev jffs2_flash_direct_writev
+#define jffs2_wbuf_timeout NULL
+#define jffs2_wbuf_process NULL
 
 #else /* NAND support present */
 
@@ -119,6 +97,8 @@
 int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
+void jffs2_wbuf_timeout(unsigned long data);
+void jffs2_wbuf_process(void *data);
 #endif /* NAND */
 
 /* background.c */
diff -Nru a/fs/jffs2/pushpull.h b/fs/jffs2/pushpull.h
--- a/fs/jffs2/pushpull.h	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/pushpull.h	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: pushpull.h,v 1.7 2002/03/06 12:37:08 dwmw2 Exp $
+ * $Id: pushpull.h,v 1.8 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jffs2/read.c b/fs/jffs2/read.c
--- a/fs/jffs2/read.c	Thu Aug  1 14:17:39 2002
+++ b/fs/jffs2/read.c	Thu Aug  1 14:17:39 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: read.c,v 1.22 2002/03/02 22:08:27 dwmw2 Exp $
+ * $Id: read.c,v 1.23 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
--- a/fs/jffs2/readinode.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/readinode.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: readinode.c,v 1.71 2002/03/06 12:25:59 dwmw2 Exp $
+ * $Id: readinode.c,v 1.73 2002/05/20 14:56:38 dwmw2 Exp $
  *
  */
 
@@ -337,6 +313,7 @@
 		printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %ld of %d bytes read\n",
 		       ret, (long)retlen, sizeof(*latest_node));
 		/* FIXME: If this fails, there seems to be a memory leak. Find it. */
+		up(&f->sem);
 		jffs2_do_clear_inode(c, f);
 		return ret?ret:-EIO;
 	}
@@ -344,6 +321,7 @@
 	crc = crc32(0, latest_node, sizeof(*latest_node)-8);
 	if (crc != latest_node->node_crc) {
 		printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", ino, fn->raw->flash_offset & ~3);
+		up(&f->sem);
 		jffs2_do_clear_inode(c, f);
 		return -EIO;
 	}
@@ -378,11 +356,13 @@
 		   kept as the metadata node */
 		if (f->metadata) {
 			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", ino, latest_node->mode);
+			up(&f->sem);
 			jffs2_do_clear_inode(c, f);
 			return -EIO;
 		}
 		if (!f->fraglist) {
 			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, latest_node->mode);
+			up(&f->sem);
 			jffs2_do_clear_inode(c, f);
 			return -EIO;
 		}
@@ -390,6 +370,7 @@
 		if (f->fraglist->next) {
 			printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, latest_node->mode);
 			/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
+			up(&f->sem);
 			jffs2_do_clear_inode(c, f);
 			return -EIO;
 		}
diff -Nru a/fs/jffs2/scan.c b/fs/jffs2/scan.c
--- a/fs/jffs2/scan.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/scan.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: scan.c,v 1.69 2002/03/08 11:03:23 dwmw2 Exp $
+ * $Id: scan.c,v 1.79 2002/07/25 20:48:51 dwmw2 Exp $
  *
  */
 #include <linux/kernel.h>
@@ -62,7 +38,6 @@
 } while(0)
 
 static uint32_t pseudo_random;
-static void jffs2_rotate_lists(struct jffs2_sb_info *c);
 
 static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
 
@@ -141,13 +116,23 @@
                            not the one with most free space.
                         */
                         if (jeb->free_size > 2*sizeof(struct jffs2_raw_inode) && 
-                                (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
+			    (jffs2_can_mark_obsolete(c) || jeb->free_size > c->wbuf_pagesize) &&
+			    (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
                                 /* Better candidate for the next writes to go to */
-                                if (c->nextblock) 
-					list_add(&c->nextblock->list, &c->dirty_list);
+                                if (c->nextblock) {
+					if (VERYDIRTY(c, c->nextblock->dirty_size)) {
+						list_add(&c->nextblock->list, &c->very_dirty_list);
+					} else {
+						list_add(&c->nextblock->list, &c->dirty_list);
+					}
+				}
                                 c->nextblock = jeb;
                         } else {
-                                list_add(&jeb->list, &c->dirty_list);
+				if (VERYDIRTY(c, jeb->dirty_size)) {
+					list_add(&jeb->list, &c->very_dirty_list);
+				} else {
+					list_add(&jeb->list, &c->dirty_list);
+				}
                         }
 			break;
 
@@ -167,14 +152,26 @@
 			bad_blocks++;
 			break;
 		default:
-			printk("jffs2_scan_medium(): unknown block state\n");
+			printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n");
 			BUG();	
 		}
 	}
 
-	/* Rotate the lists by some number to ensure wear levelling */
-	jffs2_rotate_lists(c);
+	if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) {
+		/* If we're going to start writing into a block which already 
+		   contains data, and the end of the data isn't page-aligned,
+		   skip a little and align it. */
+
+		uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1);
+
+		D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
+			  skip));
+		c->nextblock->dirty_size += skip;
+		c->dirty_size += skip;
 
+		c->nextblock->free_size -= skip;
+		c->free_size -= skip;
+	}
 	if (c->nr_erasing_blocks) {
 		if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
 			printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
@@ -245,7 +242,9 @@
 	while(ofs < jeb->offset + c->sector_size) {
 		size_t retlen;
 		ACCT_PARANOIA_CHECK(jeb);
-		
+
+		cond_resched();
+
 		if (ofs & 3) {
 			printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs);
 			ofs = (ofs+3)&~3;
@@ -323,6 +322,16 @@
 			continue;
 		}
 
+		if (ofs + node.totlen > jeb->offset + c->sector_size) {
+			/* Eep. Node goes over the end of the erase block. */
+			printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
+			       ofs, node.totlen);
+			printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
+			DIRTY_SPACE(4);
+			ofs += 4;
+			continue;
+		}
+
 		if (!(node.nodetype & JFFS2_NODE_ACCURATE)) {
 			/* Wheee. This is an obsoleted node */
 			D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
@@ -343,9 +352,9 @@
 			break;
 
 		case JFFS2_NODETYPE_CLEANMARKER:
-			if (node.totlen != sizeof(struct jffs2_unknown_node)) {
+			if (node.totlen != c->cleanmarker_size) {
 				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", 
-				       ofs, node.totlen, sizeof(struct jffs2_unknown_node));
+				       ofs, node.totlen, c->cleanmarker_size);
 				DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
 			} else if (jeb->first_node) {
 				printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
@@ -369,6 +378,11 @@
 			ofs += PAD(sizeof(struct jffs2_unknown_node));
 			break;
 
+		case JFFS2_NODETYPE_PADDING:
+			DIRTY_SPACE(PAD(node.totlen));
+			ofs += PAD(node.totlen);
+			break;
+
 		default:
 			switch (node.nodetype & JFFS2_COMPAT_MASK) {
 			case JFFS2_FEATURE_ROCOMPAT:
@@ -378,7 +392,7 @@
 					return -EROFS;
 				DIRTY_SPACE(PAD(node.totlen));
 				ofs += PAD(node.totlen);
-				continue;
+				break;
 
 			case JFFS2_FEATURE_INCOMPAT:
 				printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs);
@@ -624,7 +638,7 @@
 		if (!jeb->used_size) {
 			D1(printk(KERN_DEBUG "No valid nodes yet found in this eraseblock 0x%08x, so obsoleting the new instance at 0x%08x\n", 
 				  jeb->offset, raw->flash_offset & ~3));
-			ri.nodetype &= ~JFFS2_NODE_ACCURATE;
+ 			ri.nodetype &= ~JFFS2_NODE_ACCURATE;
 			/* Perhaps we could also mark it as such on the medium. Maybe later */
 		}
 		break;
@@ -650,7 +664,11 @@
 		tn->version = ri.version;
 
 		USED_SPACE(PAD(ri.totlen));
-		jffs2_add_tn_to_list(tn, &ic->scan->tmpnodes);
+
+		/* No need to scan from the beginning of the list again. 
+		   We can start from tn_list instead (Thanks Jocke) */
+		jffs2_add_tn_to_list(tn, tn_list);
+
 		/* Make sure the one we just added is the _last_ in the list
 		   with this version number, so the older ones get obsoleted */
 		while (tn->next && tn->next->version == tn->version) {
@@ -813,22 +831,84 @@
 	list_add(head, n);
 }
 
-static void jffs2_rotate_lists(struct jffs2_sb_info *c)
+void jffs2_rotate_lists(struct jffs2_sb_info *c)
 {
 	uint32_t x;
+	uint32_t rotateby;
 
 	x = count_list(&c->clean_list);
-	if (x)
-		rotate_list((&c->clean_list), pseudo_random % x);
+	if (x) {
+		rotateby = pseudo_random % x;
+		D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby));
+
+		rotate_list((&c->clean_list), rotateby);
+
+		D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n",
+			  list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset));
+	} else {
+		D1(printk(KERN_DEBUG "Not rotating empty clean_list\n"));
+	}
+
+	x = count_list(&c->very_dirty_list);
+	if (x) {
+		rotateby = pseudo_random % x;
+		D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby));
+
+		rotate_list((&c->very_dirty_list), rotateby);
+
+		D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n",
+			  list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset));
+	} else {
+		D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n"));
+	}
 
 	x = count_list(&c->dirty_list);
-	if (x)
-		rotate_list((&c->dirty_list), pseudo_random % x);
+	if (x) {
+		rotateby = pseudo_random % x;
+		D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby));
+
+		rotate_list((&c->dirty_list), rotateby);
+
+		D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n",
+			  list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset));
+	} else {
+		D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n"));
+	}
+
+	x = count_list(&c->erasable_list);
+	if (x) {
+		rotateby = pseudo_random % x;
+		D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby));
 
-	if (c->nr_erasing_blocks)
-		rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks);
+		rotate_list((&c->erasable_list), rotateby);
 
-	if (c->nr_free_blocks) /* Not that it should ever be zero */
-		rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks);
+		D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n",
+			  list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset));
+	} else {
+		D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n"));
+	}
+
+	if (c->nr_erasing_blocks) {
+		rotateby = pseudo_random % c->nr_erasing_blocks;
+		D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby));
+
+		rotate_list((&c->erase_pending_list), rotateby);
+
+		D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n",
+			  list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset));
+	} else {
+		D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n"));
+	}
+
+	if (c->nr_free_blocks) {
+		rotateby = pseudo_random % c->nr_free_blocks;
+		D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby));
 
+		rotate_list((&c->free_list), rotateby);
+
+		D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n",
+			  list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset));
+	} else {
+		D1(printk(KERN_DEBUG "Not rotating empty free_list\n"));
+	}
 }
diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c
--- a/fs/jffs2/super.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/super.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: super.c,v 1.64 2002/03/17 10:18:42 dwmw2 Exp $
+ * $Id: super.c,v 1.73 2002/07/23 17:00:45 dwmw2 Exp $
  *
  */
 
@@ -43,12 +19,12 @@
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/fs.h>
-#include <linux/namei.h>
 #include <linux/jffs2.h>
 #include <linux/pagemap.h>
 #include <linux/mtd/mtd.h>
 #include <linux/interrupt.h>
 #include <linux/ctype.h>
+#include <linux/namei.h>
 #include "nodelist.h"
 
 void jffs2_put_super (struct super_block *);
@@ -83,14 +59,14 @@
 
 static struct super_operations jffs2_super_operations =
 {
-	alloc_inode:	jffs2_alloc_inode,
-	destroy_inode:	jffs2_destroy_inode,
-	read_inode:	jffs2_read_inode,
-	put_super:	jffs2_put_super,
-	write_super:	jffs2_write_super,
-	statfs:		jffs2_statfs,
-	remount_fs:	jffs2_remount_fs,
-	clear_inode:	jffs2_clear_inode
+	.alloc_inode =	jffs2_alloc_inode,
+	.destroy_inode =jffs2_destroy_inode,
+	.read_inode =	jffs2_read_inode,
+	.put_super =	jffs2_put_super,
+	.write_super =	jffs2_write_super,
+	.statfs =	jffs2_statfs,
+	.remount_fs =	jffs2_remount_fs,
+	.clear_inode =	jffs2_clear_inode
 };
 
 static int jffs2_sb_compare(struct super_block *sb, void *data)
@@ -101,11 +77,11 @@
 	/* The superblocks are considered to be equivalent if the underlying MTD
 	   device is the same one */
 	if (c->mtd == p->mtd) {
-		D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", mtd->index, mtd->name));
+		D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name));
 		return 1;
 	} else {
 		D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n",
-			  c->mtd->index, c->mtd->name, mtd->index, mtd->name));
+			  c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name));
 		return 0;
 	}
 }
@@ -282,10 +258,15 @@
 
 	if (!(sb->s_flags & MS_RDONLY))
 		jffs2_stop_garbage_collect_thread(c);
+	down(&c->alloc_sem);
 	jffs2_flush_wbuf(c, 1);
+	up(&c->alloc_sem);
 	jffs2_free_ino_caches(c);
 	jffs2_free_raw_node_refs(c);
 	kfree(c->blocks);
+	if (c->wbuf)
+		kfree(c->wbuf);
+	kfree(c->inocache_list);
 	if (c->mtd->sync)
 		c->mtd->sync(c->mtd);
 
@@ -301,10 +282,10 @@
 }
  
 static struct file_system_type jffs2_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"jffs2",
-	get_sb:		jffs2_get_sb,
-	kill_sb:	jffs2_kill_sb,
+	.owner =	THIS_MODULE,
+	.name =		"jffs2",
+	.get_sb =	jffs2_get_sb,
+	.kill_sb =	jffs2_kill_sb,
 };
 
 
@@ -326,18 +307,25 @@
 	ret = jffs2_zlib_init();
 	if (ret) {
 		printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n");
-		return ret;
+		goto out;
 	}
 	ret = jffs2_create_slab_caches();
 	if (ret) {
 		printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n");
-		return ret;
+		goto out_zlib;
 	}
 	ret = register_filesystem(&jffs2_fs_type);
 	if (ret) {
 		printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n");
-		jffs2_destroy_slab_caches();
+		goto out_slab;
 	}
+	return 0;
+
+ out_slab:
+	jffs2_destroy_slab_caches();
+ out_zlib:
+	jffs2_zlib_exit();
+ out:
 	return ret;
 }
 
diff -Nru a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c
--- a/fs/jffs2/symlink.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jffs2/symlink.c	Thu Aug  1 14:17:36 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: symlink.c,v 1.9 2002/01/10 09:29:53 dwmw2 Exp $
+ * $Id: symlink.c,v 1.11 2002/07/23 17:00:45 dwmw2 Exp $
  *
  */
 
@@ -46,9 +22,9 @@
 
 struct inode_operations jffs2_symlink_inode_operations =
 {	
-	readlink:	jffs2_readlink,
-	follow_link:	jffs2_follow_link,
-	setattr:	jffs2_setattr
+	.readlink =	jffs2_readlink,
+	.follow_link =	jffs2_follow_link,
+	.setattr =	jffs2_setattr
 };
 
 int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen)
diff -Nru a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
--- a/fs/jffs2/wbuf.c	Thu Aug  1 14:17:39 2002
+++ b/fs/jffs2/wbuf.c	Thu Aug  1 14:17:39 2002
@@ -5,34 +5,10 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
- *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: wbuf.c,v 1.7 2002/03/08 11:27:59 dwmw2 Exp $
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
+ * $Id: wbuf.c,v 1.12 2002/05/20 14:56:39 dwmw2 Exp $
+ * -- with the NAND definitions added back pending MTD update for 2.5.
  */
 
 #include <linux/kernel.h>
@@ -51,25 +27,100 @@
 #define NAND_JFFS2_OOB8_FSDALEN		2
 #define NAND_JFFS2_OOB16_FSDALEN	8
 
+
+/* max. erase failures before we mark a block bad */
 #define MAX_ERASE_FAILURES 	5
 
+/* two seconds timeout for timed wbuf-flushing */
+#define WBUF_FLUSH_TIMEOUT	2 * HZ
+
 static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c)
 {
 	struct list_head *this, *next;
+	static int n;
 
 	if (list_empty(&c->erasable_pending_wbuf_list))
 		return;
 
 	list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) {
+		struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
+
+		D1(printk(KERN_DEBUG "Removing eraseblock at 0x%08x from erasable_pending_wbuf_list...\n", jeb->offset));
 		list_del(this);
-		list_add_tail(this, &c->erasable_list);
+		if ((jiffies + (n++)) & 127) {
+			/* Most of the time, we just erase it immediately. Otherwise we
+			   spend ages scanning it on mount, etc. */
+			D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n"));
+			list_add_tail(&jeb->list, &c->erase_pending_list);
+			c->nr_erasing_blocks++;
+			jffs2_erase_pending_trigger(c);
+		} else {
+			/* Sometimes, however, we leave it elsewhere so it doesn't get
+			   immediately reused, and we spread the load a bit. */
+			D1(printk(KERN_DEBUG "...and adding to erasable_list\n"));
+			list_add_tail(&jeb->list, &c->erasable_list);
+		}
 	}
 }
 
+/* 
+*	Timed flushing of wbuf. If we have no consecutive write to wbuf, within	
+*	the specified time, we flush the contents with padding !
+*/
+void jffs2_wbuf_timeout (unsigned long data)
+{
+	struct jffs2_sb_info *c = (struct jffs2_sb_info *) data;
+	/* 
+	* Wake up the flush process, we need process context to have the right 
+	* to sleep on flash write
+	*/
+	D1(printk(KERN_DEBUG "jffs2_wbuf_timeout(): timer expired\n"));
+	schedule_task(&c->wbuf_task);
+}
+
+/*
+*	Process for timed wbuf flush
+*
+*	FIXME What happens, if we have a write failure there ????
+*/
+void jffs2_wbuf_process (void *data)
+{
+	struct jffs2_sb_info *c = (struct jffs2_sb_info *) data;	
+	
+	D1(printk(KERN_DEBUG "jffs2_wbuf_process() entered\n"));
+
+	if (!down_trylock(&c->alloc_sem)) {
+		D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n"));
+	
+		if(!c->nextblock || (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)))
+			jffs2_flush_wbuf(c, 1); /* pad only */
+		else			
+			jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */
+		up(&c->alloc_sem);
+	} else {
+		D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem already occupied\n"));
+	}	
+}
+
+
+/* Meaning of pad argument:
+   0: Do not pad. Probably pointless - we only ever use this when we can't pad anyway.
+   1: Pad, do not adjust nextblock free_size
+   2: Pad, adjust nextblock free_size
+*/
 int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 {
 	int ret;
 	size_t retlen;
+	
+	if (!down_trylock(&c->alloc_sem)) {
+		up(&c->alloc_sem);
+		printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
+		BUG();
+	}
+
+	/* delete a eventually started timed wbuf flush */
+	del_timer_sync(&c->wbuf_timer);
 
 	if(!c->wbuf || !c->wbuf_len)
 		return 0;
@@ -339,6 +390,11 @@
 
 alldone:	
 	*retlen = donelen;
+	/* Setup timed wbuf flush, if buffer len != 0 */
+	if (c->wbuf_len) {
+		D1(printk (KERN_DEBUG "jffs2_flash_writev: mod wbuf_timer\n"));	
+		mod_timer(&c->wbuf_timer, jiffies + WBUF_FLUSH_TIMEOUT);
+	}
 	return 0;
 }
 
diff -Nru a/fs/jffs2/write.c b/fs/jffs2/write.c
--- a/fs/jffs2/write.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/write.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: write.c,v 1.52 2002/03/08 11:01:43 dwmw2 Exp $
+ * $Id: write.c,v 1.56 2002/07/10 14:05:16 dwmw2 Exp $
  *
  */
 
@@ -89,7 +65,7 @@
 			ret = 1;
 	}
 	if (ret) {
-		printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there's data already there:\n", ofs);
+		printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs);
 		printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", 
 		       ofs,
 		       buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
@@ -386,8 +362,10 @@
 	 */
 	ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
 	D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
-	if (ret)
+	if (ret) {
+		up(&f->sem);
 		return ret;
+	}
 
 	ri->data_crc = 0;
 	ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
@@ -472,7 +450,8 @@
 }
 
 
-int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f)
+int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
+		    const char *name, int namelen, struct jffs2_inode_info *dead_f)
 {
 	struct jffs2_raw_dirent *rd;
 	struct jffs2_full_dirent *fd;
@@ -522,7 +501,10 @@
 	jffs2_complete_reservation(c);
 	up(&dir_f->sem);
 	
-	if (dead_f) { /* Null if this was a rename not a real unlink */
+	/* dead_f is NULL if this was a rename not a real unlink */
+	/* Also catch the !f->inocache case, where there was a dirent
+	   pointing to an inode which didn't exist. */
+	if (dead_f && dead_f->inocache) { 
 
 		down(&dead_f->sem);
 
diff -Nru a/fs/jffs2/writev.c b/fs/jffs2/writev.c
--- a/fs/jffs2/writev.c	Thu Aug  1 14:17:40 2002
+++ b/fs/jffs2/writev.c	Thu Aug  1 14:17:40 2002
@@ -5,33 +5,9 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in this directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: writev.c,v 1.1 2002/03/08 11:27:59 dwmw2 Exp $
+ * $Id: writev.c,v 1.2 2002/05/20 14:56:39 dwmw2 Exp $
  *
  */
 
diff -Nru a/fs/jfs/file.c b/fs/jfs/file.c
--- a/fs/jfs/file.c	Thu Aug  1 14:17:39 2002
+++ b/fs/jfs/file.c	Thu Aug  1 14:17:39 2002
@@ -98,5 +98,6 @@
 	.write		= generic_file_write,
 	.read		= generic_file_read,
 	.mmap		= generic_file_mmap,
+ 	.sendfile	= generic_file_sendfile,
 	.fsync		= jfs_fsync,
 };
diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	Thu Aug  1 14:17:36 2002
+++ b/fs/jfs/inode.c	Thu Aug  1 14:17:36 2002
@@ -293,10 +293,23 @@
 	return generic_block_bmap(mapping, block, jfs_get_block);
 }
 
+static int
+jfs_get_blocks(struct inode *inode, sector_t iblock, unsigned long max_blocks,
+			struct buffer_head *bh_result, int create)
+{
+	int ret;
+
+	ret = jfs_get_block(inode, iblock, bh_result, create);
+	if (ret == 0)
+		bh_result->b_size = (1 << inode->i_blkbits);
+	return ret;
+}
+
 static int jfs_direct_IO(int rw, struct inode *inode, char *buf,
 			loff_t offset, size_t count)
 {
-	return generic_direct_IO(rw, inode, buf, offset, count, jfs_get_block);
+	return generic_direct_IO(rw, inode, buf,
+				offset, count, jfs_get_blocks);
 }
 
 struct address_space_operations jfs_aops = {
diff -Nru a/fs/jfs/namei.c b/fs/jfs/namei.c
--- a/fs/jfs/namei.c	Thu Aug  1 14:17:41 2002
+++ b/fs/jfs/namei.c	Thu Aug  1 14:17:41 2002
@@ -399,8 +399,6 @@
 
 	IWRITE_UNLOCK(dip);
 
-	d_delete(dentry);
-
       out2:
 	free_UCSname(&dname);
 
@@ -542,8 +540,6 @@
 	}
 
 	IWRITE_UNLOCK(dip);
-
-	d_delete(dentry);
 
       out1:
 	free_UCSname(&dname);
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Thu Aug  1 14:17:41 2002
+++ b/fs/locks.c	Thu Aug  1 14:17:41 2002
@@ -477,27 +477,21 @@
 }
 
 /*
- * Remove lock from the lock lists
+ * Delete a lock and then free it.
+ * Wake up processes that are blocked waiting for this lock,
+ * notify the FS that the lock has been cleared and
+ * finally free the lock.
  */
-static inline void _unhash_lock(struct file_lock **thisfl_p)
+static void locks_delete_lock(struct file_lock **thisfl_p)
 {
 	struct file_lock *fl = *thisfl_p;
 
 	*thisfl_p = fl->fl_next;
 	fl->fl_next = NULL;
-
 	list_del_init(&fl->fl_link);
-}
 
-/*
- * Wake up processes that are blocked waiting for this lock,
- * notify the FS that the lock has been cleared and
- * finally free the lock.
- */
-static inline void _delete_lock(struct file_lock *fl)
-{
 	fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
-	if (fl->fl_fasync != NULL){
+	if (fl->fl_fasync != NULL) {
 		printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
 		fl->fl_fasync = NULL;
 	}
@@ -509,36 +503,6 @@
 	locks_free_lock(fl);
 }
 
-/*
- * Delete a lock and then free it.
- */
-static void locks_delete_lock(struct file_lock **thisfl_p)
-{
-	struct file_lock *fl = *thisfl_p;
-
-	_unhash_lock(thisfl_p);
-	_delete_lock(fl);
-}
-
-/*
- * Call back client filesystem in order to get it to unregister a lock,
- * then delete lock. Essentially useful only in locks_remove_*().
- * Note: this must be called with the semaphore already held!
- */
-static inline void locks_unlock_delete(struct file_lock **thisfl_p)
-{
-	struct file_lock *fl = *thisfl_p;
-	int (*lock)(struct file *, int, struct file_lock *);
-
-	_unhash_lock(thisfl_p);
-	if (fl->fl_file->f_op &&
-	    (lock = fl->fl_file->f_op->lock) != NULL) {
-		fl->fl_type = F_UNLCK;
-		lock(fl->fl_file, F_SETLK, fl);
-	}
-	_delete_lock(fl);
-}
-
 /* Determine if lock sys_fl blocks lock caller_fl. Common functionality
  * checks for shared/exclusive status of overlapping locks.
  */
@@ -1242,6 +1206,9 @@
 		return -EACCES;
 	if (!S_ISREG(inode->i_mode))
 		return -EINVAL;
+	error = security_ops->file_lock(filp, arg);
+	if (error)
+		return error;
 
 	lock_kernel();
 
@@ -1359,8 +1326,7 @@
 	if (error < 0)
 		goto out_putf;
 
-	error = security_ops->file_lock(filp, cmd,
-					(cmd & LOCK_NB) ? 0 : 1);
+	error = security_ops->file_lock(filp, lock->fl_type);
 	if (error)
 		goto out_putf;
 
@@ -1494,8 +1460,7 @@
 		goto out;
 	}
 
-	error = security_ops->file_lock(filp, file_lock->fl_type,
-	                                cmd == F_SETLKW);
+	error = security_ops->file_lock(filp, file_lock->fl_type);
 	if (error)
 		goto out;
 
@@ -1618,8 +1583,7 @@
 		goto out;
 	}
 
-	error = security_ops->file_lock(filp, file_lock->fl_type,
-					cmd == F_SETLKW64);
+	error = security_ops->file_lock(filp, file_lock->fl_type);
 	if (error)
 		goto out;
 
@@ -1638,37 +1602,27 @@
 
 /*
  * This function is called when the file is being removed
- * from the task's fd array.
+ * from the task's fd array.  POSIX locks belonging to this task
+ * are deleted at this time.
  */
 void locks_remove_posix(struct file *filp, fl_owner_t owner)
 {
-	struct inode * inode = filp->f_dentry->d_inode;
-	struct file_lock *fl;
-	struct file_lock **before;
+	struct file_lock lock;
 
-	/*
-	 * For POSIX locks we free all locks on this file for the given task.
-	 */
-	if (!inode->i_flock) {
-		/*
-		 * Notice that something might be grabbing a lock right now.
-		 * Consider it as a race won by us - event is async, so even if
-		 * we miss the lock added we can trivially consider it as added
-		 * after we went through this call.
-		 */
-		return;
-	}
-	lock_kernel();
-	before = &inode->i_flock;
-	while ((fl = *before) != NULL) {
-		if (IS_POSIX(fl) && fl->fl_owner == owner) {
-			locks_unlock_delete(before);
-			before = &inode->i_flock;
-			continue;
-		}
-		before = &fl->fl_next;
+	lock.fl_type = F_UNLCK;
+	lock.fl_flags = FL_POSIX;
+	lock.fl_start = 0;
+	lock.fl_end = OFFSET_MAX;
+	lock.fl_owner = owner;
+	lock.fl_pid = current->pid;
+	lock.fl_file = filp;
+
+	if (filp->f_op && filp->f_op->lock != NULL) {
+		filp->f_op->lock(filp, F_SETLK, &lock);
+		/* Ignore any error -- we must remove the locks anyway */
 	}
-	unlock_kernel();
+
+	posix_lock_file(filp, &lock, 0);
 }
 
 /*
diff -Nru a/fs/minix/file.c b/fs/minix/file.c
--- a/fs/minix/file.c	Thu Aug  1 14:17:40 2002
+++ b/fs/minix/file.c	Thu Aug  1 14:17:40 2002
@@ -21,6 +21,7 @@
 	write:		generic_file_write,
 	mmap:		generic_file_mmap,
 	fsync:		minix_sync_file,
+	sendfile:	generic_file_sendfile,
 };
 
 struct inode_operations minix_file_inode_operations = {
diff -Nru a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
--- a/fs/ncpfs/dir.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ncpfs/dir.c	Thu Aug  1 14:17:40 2002
@@ -51,22 +51,22 @@
 		      
 struct file_operations ncp_dir_operations =
 {
-	read:		generic_read_dir,
-	readdir:	ncp_readdir,
-	ioctl:		ncp_ioctl,
+	.read		= generic_read_dir,
+	.readdir	= ncp_readdir,
+	.ioctl		= ncp_ioctl,
 };
 
 struct inode_operations ncp_dir_inode_operations =
 {
-	create:		ncp_create,
-	lookup:		ncp_lookup,
-	unlink:		ncp_unlink,
-	symlink:	ncp_symlink,
-	mkdir:		ncp_mkdir,
-	rmdir:		ncp_rmdir,
-	mknod:		ncp_mknod,
-	rename:		ncp_rename,
-	setattr:	ncp_notify_change,
+	.create		= ncp_create,
+	.lookup		= ncp_lookup,
+	.unlink		= ncp_unlink,
+	.symlink	= ncp_symlink,
+	.mkdir		= ncp_mkdir,
+	.rmdir		= ncp_rmdir,
+	.mknod		= ncp_mknod,
+	.rename		= ncp_rename,
+	.setattr	= ncp_notify_change,
 };
 
 /*
@@ -79,17 +79,17 @@
 
 static struct dentry_operations ncp_dentry_operations =
 {
-	d_revalidate:	ncp_lookup_validate,
-	d_hash:		ncp_hash_dentry,
-	d_compare:	ncp_compare_dentry,
-	d_delete:	ncp_delete_dentry,
+	.d_revalidate	= ncp_lookup_validate,
+	.d_hash		= ncp_hash_dentry,
+	.d_compare	= ncp_compare_dentry,
+	.d_delete	= ncp_delete_dentry,
 };
 
 struct dentry_operations ncp_root_dentry_operations =
 {
-	d_hash:		ncp_hash_dentry,
-	d_compare:	ncp_compare_dentry,
-	d_delete:	ncp_delete_dentry,
+	.d_hash		= ncp_hash_dentry,
+	.d_compare	= ncp_compare_dentry,
+	.d_delete	= ncp_delete_dentry,
 };
 
 
diff -Nru a/fs/ncpfs/file.c b/fs/ncpfs/file.c
--- a/fs/ncpfs/file.c	Thu Aug  1 14:17:36 2002
+++ b/fs/ncpfs/file.c	Thu Aug  1 14:17:36 2002
@@ -296,16 +296,16 @@
 
 struct file_operations ncp_file_operations =
 {
-	llseek:		remote_llseek,
-	read:		ncp_file_read,
-	write:		ncp_file_write,
-	ioctl:		ncp_ioctl,
-	mmap:		ncp_mmap,
-	release:	ncp_release,
-	fsync:		ncp_fsync,
+	.llseek		= remote_llseek,
+	.read		= ncp_file_read,
+	.write		= ncp_file_write,
+	.ioctl		= ncp_ioctl,
+	.mmap		= ncp_mmap,
+	.release	= ncp_release,
+	.fsync		= ncp_fsync,
 };
 
 struct inode_operations ncp_file_inode_operations =
 {
-	setattr:	ncp_notify_change,
+	.setattr	= ncp_notify_change,
 };
diff -Nru a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c
--- a/fs/ncpfs/inode.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ncpfs/inode.c	Thu Aug  1 14:17:40 2002
@@ -83,12 +83,12 @@
 
 static struct super_operations ncp_sops =
 {
-	alloc_inode:	ncp_alloc_inode,
-	destroy_inode:	ncp_destroy_inode,
-	drop_inode:	generic_delete_inode,
-	delete_inode:	ncp_delete_inode,
-	put_super:	ncp_put_super,
-	statfs:		ncp_statfs,
+	.alloc_inode	= ncp_alloc_inode,
+	.destroy_inode	= ncp_destroy_inode,
+	.drop_inode	= generic_delete_inode,
+	.delete_inode	= ncp_delete_inode,
+	.put_super	= ncp_put_super,
+	.statfs		= ncp_statfs,
 };
 
 extern struct dentry_operations ncp_root_dentry_operations;
@@ -792,10 +792,10 @@
 }
 
 static struct file_system_type ncp_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"ncpfs",
-	get_sb:		ncp_get_sb,
-	kill_sb:	kill_anon_super,
+	.owner		= THIS_MODULE,
+	.name		= "ncpfs",
+	.get_sb		= ncp_get_sb,
+	.kill_sb	= kill_anon_super,
 };
 
 static int __init init_ncp_fs(void)
diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	Thu Aug  1 14:17:40 2002
+++ b/fs/nfs/dir.c	Thu Aug  1 14:17:40 2002
@@ -37,6 +37,8 @@
 
 static int nfs_readdir(struct file *, void *, filldir_t);
 static struct dentry *nfs_lookup(struct inode *, struct dentry *);
+static int nfs_cached_lookup(struct inode *, struct dentry *,
+				struct nfs_fh *, struct nfs_fattr *);
 static int nfs_create(struct inode *, struct dentry *, int);
 static int nfs_mkdir(struct inode *, struct dentry *, int);
 static int nfs_rmdir(struct inode *, struct dentry *);
@@ -107,14 +109,16 @@
  again:
 	error = NFS_PROTO(inode)->readdir(inode, cred, desc->entry->cookie, page,
 					  NFS_SERVER(inode)->dtsize, desc->plus);
-	/* We requested READDIRPLUS, but the server doesn't grok it */
-	if (desc->plus && error == -ENOTSUPP) {
-		NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
-		desc->plus = 0;
-		goto again;
-	}
-	if (error < 0)
+	if (error < 0) {
+		/* We requested READDIRPLUS, but the server doesn't grok it */
+		if (error == -ENOTSUPP && desc->plus) {
+			NFS_SERVER(inode)->caps &= ~NFS_CAP_READDIRPLUS;
+			NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
+			desc->plus = 0;
+			goto again;
+		}
 		goto error;
+	}
 	SetPageUptodate(page);
 	/* Ensure consistent page alignment of the data.
 	 * Note: assumes we have exclusive access to this mapping either
@@ -194,8 +198,7 @@
 
 	dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index);
 
-	desc->plus = NFS_USE_READDIRPLUS(inode);
-	page = read_cache_page(&inode->i_data, desc->page_index,
+	page = read_cache_page(inode->i_mapping, desc->page_index,
 			       (filler_t *)nfs_readdir_filler, desc);
 	if (IS_ERR(page)) {
 		status = PTR_ERR(page);
@@ -246,6 +249,24 @@
 	return res;
 }
 
+static unsigned int nfs_type2dtype[] = {
+	DT_UNKNOWN,
+	DT_REG,
+	DT_DIR,
+	DT_BLK,
+	DT_CHR,
+	DT_LNK,
+	DT_SOCK,
+	DT_UNKNOWN,
+	DT_FIFO
+};
+
+static inline
+unsigned int nfs_type_to_d_type(enum nfs_ftype type)
+{
+	return nfs_type2dtype[type];
+}
+
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -262,11 +283,17 @@
 	dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target);
 
 	for(;;) {
+		unsigned d_type = DT_UNKNOWN;
 		/* Note: entry->prev_cookie contains the cookie for
 		 *	 retrieving the current dirent on the server */
 		fileid = nfs_fileid_to_ino_t(entry->ino);
+
+		/* Use readdirplus info */
+		if (desc->plus && (entry->fattr->valid & NFS_ATTR_FATTR))
+			d_type = nfs_type_to_d_type(entry->fattr->type);
+
 		res = filldir(dirent, entry->name, entry->len, 
-			      entry->prev_cookie, fileid, DT_UNKNOWN);
+			      entry->prev_cookie, fileid, d_type);
 		if (res < 0)
 			break;
 		file->f_pos = desc->target = entry->cookie;
@@ -333,7 +360,8 @@
 	/* Reset read descriptor so it searches the page cache from
 	 * the start upon the next call to readdir_search_pagecache() */
 	desc->page_index = 0;
-	memset(desc->entry, 0, sizeof(*desc->entry));
+	desc->entry->cookie = desc->entry->prev_cookie = 0;
+	desc->entry->eof = 0;
  out:
 	dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status);
 	return status;
@@ -352,6 +380,8 @@
 	nfs_readdir_descriptor_t my_desc,
 			*desc = &my_desc;
 	struct nfs_entry my_entry;
+	struct nfs_fh	 fh;
+	struct nfs_fattr fattr;
 	long		res;
 
 	lock_kernel();
@@ -369,12 +399,17 @@
 	 * itself.
 	 */
 	memset(desc, 0, sizeof(*desc));
-	memset(&my_entry, 0, sizeof(my_entry));
 
 	desc->file = filp;
 	desc->target = filp->f_pos;
-	desc->entry = &my_entry;
 	desc->decode = NFS_PROTO(inode)->decode_dirent;
+	desc->plus = NFS_USE_READDIRPLUS(inode);
+
+	my_entry.cookie = my_entry.prev_cookie = 0;
+	my_entry.eof = 0;
+	my_entry.fh = &fh;
+	my_entry.fattr = &fattr;
+	desc->entry = &my_entry;
 
 	while(!desc->entry->eof) {
 		res = readdir_search_pagecache(desc);
@@ -495,6 +530,15 @@
 		goto out_valid;
 	}
 
+	error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
+	if (!error) {
+		if (memcmp(NFS_FH(inode), &fhandle, sizeof(struct nfs_fh))!= 0)
+			goto out_bad;
+		if (nfs_lookup_verify_inode(inode))
+			goto out_bad;
+		goto out_valid_renew;
+	}
+
 	if (NFS_STALE(inode))
 		goto out_bad;
 
@@ -506,6 +550,7 @@
 	if ((error = nfs_refresh_inode(inode, &fattr)) != 0)
 		goto out_bad;
 
+ out_valid_renew:
 	nfs_renew_times(dentry);
  out_valid:
 	unlock_kernel();
@@ -569,7 +614,7 @@
 
 static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry)
 {
-	struct inode *inode;
+	struct inode *inode = NULL;
 	int error;
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
@@ -585,8 +630,19 @@
 	dentry->d_op = &nfs_dentry_operations;
 
 	lock_kernel();
+	error = nfs_cached_lookup(dir, dentry, &fhandle, &fattr);
+	if (!error) {
+		error = -EACCES;
+		inode = nfs_fhget(dentry, &fhandle, &fattr);
+		if (inode) {
+			d_add(dentry, inode);
+			nfs_renew_times(dentry);
+			error = 0;
+		}
+		goto out_unlock;
+	}
+
 	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
-	inode = NULL;
 	if (error == -ENOENT)
 		goto no_entry;
 	if (!error) {
@@ -599,9 +655,84 @@
 		}
 		nfs_renew_times(dentry);
 	}
+out_unlock:
 	unlock_kernel();
 out:
+	BUG_ON(error > 0);
 	return ERR_PTR(error);
+}
+
+static inline
+int find_dirent_name(nfs_readdir_descriptor_t *desc, struct page *page, struct dentry *dentry)
+{
+	struct nfs_entry *entry = desc->entry;
+	int		 status;
+
+	while((status = dir_decode(desc)) == 0) {
+		if (entry->len != dentry->d_name.len)
+			continue;
+		if (memcmp(entry->name, dentry->d_name.name, entry->len))
+			continue;
+		if (!(entry->fattr->valid & NFS_ATTR_FATTR))
+			continue;
+		break;
+	}
+	return status;
+}
+
+/*
+ * Use the cached Readdirplus results in order to avoid a LOOKUP call
+ * whenever we believe that the parent directory has not changed.
+ *
+ * We assume that any file creation/rename changes the directory mtime.
+ * As this results in a page cache invalidation whenever it occurs,
+ * we don't require any other tests for cache coherency.
+ */
+static
+int nfs_cached_lookup(struct inode *dir, struct dentry *dentry,
+			struct nfs_fh *fh, struct nfs_fattr *fattr)
+{
+	nfs_readdir_descriptor_t desc;
+	struct nfs_server *server;
+	struct nfs_entry entry;
+	struct page *page;
+	unsigned long timestamp = NFS_MTIME_UPDATE(dir);
+	int res;
+
+	if (!NFS_USE_READDIRPLUS(dir))
+		return -ENOENT;
+	server = NFS_SERVER(dir);
+	if (server->flags & NFS_MOUNT_NOAC)
+		return -ENOENT;
+	nfs_revalidate_inode(server, dir);
+
+	entry.fh = fh;
+	entry.fattr = fattr;
+
+	desc.decode = NFS_PROTO(dir)->decode_dirent;
+	desc.entry = &entry;
+	desc.page_index = 0;
+	desc.plus = 1;
+
+	for(;(page = find_get_page(dir->i_mapping, desc.page_index)); desc.page_index++) {
+
+		res = -EIO;
+		if (PageUptodate(page)) {
+			desc.ptr = kmap(page);
+			res = find_dirent_name(&desc, page, dentry);
+			kunmap(page);
+		}
+		page_cache_release(page);
+
+		if (res == 0)
+			goto out_found;
+		if (res != -EAGAIN)
+			break;
+	}
+	return -ENOENT;
+ out_found:
+	fattr->timestamp = timestamp;
+	return 0;
 }
 
 /*
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	Thu Aug  1 14:17:41 2002
+++ b/fs/nfs/inode.c	Thu Aug  1 14:17:41 2002
@@ -283,12 +283,14 @@
 	INIT_LIST_HEAD(&server->lru_busy);
 
  nfsv3_try_again:
+	server->caps = 0;
 	/* Check NFS protocol revision and initialize RPC op vector
 	 * and file handle pool. */
 	if (data->flags & NFS_MOUNT_VER3) {
 #ifdef CONFIG_NFS_V3
 		server->rpc_ops = &nfs_v3_clientops;
 		version = 3;
+		server->caps |= NFS_CAP_READDIRPLUS;
 		if (data->version < 4) {
 			printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
 			goto out_unlock;
@@ -642,6 +644,9 @@
 	return __nfs_fhget(sb, fhandle, fattr);
 }
 
+/* Don't use READDIRPLUS on directories that we believe are too large */
+#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)
+
 /*
  * Look up the inode by super block and fattr->fileid.
  */
@@ -690,6 +695,9 @@
 		} else if (S_ISDIR(inode->i_mode)) {
 			inode->i_op = &nfs_dir_inode_operations;
 			inode->i_fop = &nfs_dir_operations;
+			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
+			    && fattr->size <= NFS_LIMIT_READDIRPLUS)
+				NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS;
 		} else if (S_ISLNK(inode->i_mode))
 			inode->i_op = &nfs_symlink_inode_operations;
 		else
@@ -700,13 +708,13 @@
 		new_isize = nfs_size_to_loff_t(fattr->size);
 		new_atime = nfs_time_to_secs(fattr->atime);
 
-		NFS_READTIME(inode) = jiffies;
+		NFS_READTIME(inode) = fattr->timestamp;
 		NFS_CACHE_CTIME(inode) = fattr->ctime;
 		inode->i_ctime = nfs_time_to_secs(fattr->ctime);
 		inode->i_atime = new_atime;
 		NFS_CACHE_MTIME(inode) = new_mtime;
 		inode->i_mtime = nfs_time_to_secs(new_mtime);
-		NFS_MTIME_UPDATE(inode) = jiffies;
+		NFS_MTIME_UPDATE(inode) = fattr->timestamp;
 		NFS_CACHE_ISIZE(inode) = new_size;
 		inode->i_size = new_isize;
 		inode->i_mode = fattr->mode;
@@ -1014,6 +1022,9 @@
 		goto out_err;
 	}
 
+	/* Throw out obsolete READDIRPLUS attributes */
+	if (time_before(fattr->timestamp, NFS_READTIME(inode)))
+		return 0;
 	/*
 	 * Make sure the inode's type hasn't changed.
 	 */
@@ -1032,7 +1043,7 @@
 	/*
 	 * Update the read time so we don't revalidate too often.
 	 */
-	NFS_READTIME(inode) = jiffies;
+	NFS_READTIME(inode) = fattr->timestamp;
 
 	/*
 	 * Note: NFS_CACHE_ISIZE(inode) reflects the state of the cache.
@@ -1082,7 +1093,7 @@
 
 	if (NFS_CACHE_MTIME(inode) != new_mtime) {
 		if (invalid)
-			NFS_MTIME_UPDATE(inode) = jiffies;
+			NFS_MTIME_UPDATE(inode) = fattr->timestamp;
 		NFS_CACHE_MTIME(inode) = new_mtime;
 		inode->i_mtime = nfs_time_to_secs(new_mtime);
 	}
diff -Nru a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
--- a/fs/nfs/nfs2xdr.c	Thu Aug  1 14:17:40 2002
+++ b/fs/nfs/nfs2xdr.c	Thu Aug  1 14:17:40 2002
@@ -118,6 +118,7 @@
 		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
 		fattr->rdev = 0;
 	}
+	fattr->timestamp = jiffies;
 	return p;
 }
 
@@ -419,9 +420,9 @@
 	kunmap(*page);
 	return nr;
  short_pkt:
-	kunmap(*page);
 	printk(KERN_NOTICE "NFS: short packet in readdir reply!\n");
 	entry[0] = entry[1] = 0;
+	kunmap(*page);
 	return nr;
 err_unmap:
 	kunmap(*page);
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	Thu Aug  1 14:17:41 2002
+++ b/fs/nfs/nfs3xdr.c	Thu Aug  1 14:17:41 2002
@@ -181,6 +181,7 @@
 
 	/* Update the mode bits */
 	fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
+	fattr->timestamp = jiffies;
 	return p;
 }
 
@@ -573,10 +574,10 @@
 	kunmap(*page);
 	return nr;
  short_pkt:
-	kunmap(*page);
 	printk(KERN_NOTICE "NFS: short packet in readdir reply!\n");
 	/* truncate listing */
 	entry[0] = entry[1] = 0;
+	kunmap(*page);
 	return nr;
 err_unmap:
 	kunmap(*page);
@@ -603,21 +604,19 @@
 	p = xdr_decode_hyper(p, &entry->cookie);
 
 	if (plus) {
-		p = xdr_decode_post_op_attr(p, &entry->fattr);
+		entry->fattr->valid = 0;
+		p = xdr_decode_post_op_attr(p, entry->fattr);
 		/* In fact, a post_op_fh3: */
 		if (*p++) {
-			p = xdr_decode_fhandle(p, &entry->fh);
+			p = xdr_decode_fhandle(p, entry->fh);
 			/* Ugh -- server reply was truncated */
 			if (p == NULL) {
 				dprintk("NFS: FH truncated\n");
 				*entry = old;
 				return ERR_PTR(-EAGAIN);
 			}
-		} else {
-			/* If we don't get a file handle, the attrs
-			 * aren't worth a lot. */
-			entry->fattr.valid = 0;
-		}
+		} else
+			memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
 	}
 
 	entry->eof = !p[0] && p[1];
diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c
--- a/fs/nfs/write.c	Thu Aug  1 14:17:37 2002
+++ b/fs/nfs/write.c	Thu Aug  1 14:17:37 2002
@@ -808,8 +808,15 @@
 	 * If wsize is smaller than page size, update and write
 	 * page synchronously.
 	 */
-	if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE || IS_SYNC(inode))
-		return nfs_writepage_sync(file, inode, page, offset, count);
+	if (NFS_SERVER(inode)->wsize < PAGE_CACHE_SIZE || IS_SYNC(inode)) {
+		status = nfs_writepage_sync(file, inode, page, offset, count);
+		if (status > 0) {
+			if (offset == 0 && status == PAGE_CACHE_SIZE)
+				SetPageUptodate(page);
+			return 0;
+		}
+		return status;
+	}
 
 	/*
 	 * Try to find an NFS request corresponding to this page
diff -Nru a/fs/ntfs/file.c b/fs/ntfs/file.c
--- a/fs/ntfs/file.c	Thu Aug  1 14:17:41 2002
+++ b/fs/ntfs/file.c	Thu Aug  1 14:17:41 2002
@@ -52,6 +52,7 @@
 	llseek:		generic_file_llseek,	/* Seek inside file. */
 	read:		generic_file_read,	/* Read from file. */
 	mmap:		generic_file_mmap,	/* Mmap file. */
+ 	sendfile:	generic_file_sendfile,	/* Zero-copy data send */
 	open:		ntfs_file_open,		/* Open file. */
 };
 
diff -Nru a/fs/partitions/Config.in b/fs/partitions/Config.in
--- a/fs/partitions/Config.in	Thu Aug  1 14:17:39 2002
+++ b/fs/partitions/Config.in	Thu Aug  1 14:17:39 2002
@@ -25,7 +25,7 @@
       bool '    Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
       bool '    Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
    fi
-   dep_bool '  Windows Logical Disk Manager (Dynamic Disk) support' CONFIG_LDM_PARTITION
+   bool '  Windows Logical Disk Manager (Dynamic Disk) support' CONFIG_LDM_PARTITION
    if [ "$CONFIG_LDM_PARTITION" = "y" ]; then
       bool '    Windows LDM extra logging' CONFIG_LDM_DEBUG
    fi
diff -Nru a/fs/partitions/check.c b/fs/partitions/check.c
--- a/fs/partitions/check.c	Thu Aug  1 14:17:40 2002
+++ b/fs/partitions/check.c	Thu Aug  1 14:17:40 2002
@@ -107,11 +107,13 @@
 	const char *maj = hd->major_name;
 	unsigned int unit = (minor >> hd->minor_shift);
 	unsigned int part = (minor & ((1 << hd->minor_shift) -1 ));
+	struct hd_struct *p = hd->part + minor - hd->first_minor;
 
-	if ((unit < hd->nr_real) && hd->part[minor].de) {
+	if ((((minor - hd->first_minor) >> hd->minor_shift) < hd->nr_real) &&
+	     p->de) {
 		int pos;
 
-		pos = devfs_generate_path (hd->part[minor].de, buf, 64);
+		pos = devfs_generate_path(p->de, buf, 64);
 		if (pos >= 0)
 			return buf + pos;
 	}
@@ -210,33 +212,25 @@
 	kdev.value=(int)(long)driverfs_dev->driver_data;
 	return off ? 0 : sprintf (page, "%x\n",kdev.value);
 }
-static struct driver_file_entry partition_device_kdev_file = {
-	name: "kdev",
-	mode: S_IRUGO,
-	show: partition_device_kdev_read,
-};
+static DEVICE_ATTR(kdev,"kdev",S_IRUGO,partition_device_kdev_read,NULL);
 
 static ssize_t partition_device_type_read(struct device *driverfs_dev, 
 			char *page, size_t count, loff_t off) 
 {
 	return off ? 0 : sprintf (page, "BLK\n");
 }
-static struct driver_file_entry partition_device_type_file = {
-	name: "type",
-	mode: S_IRUGO,
-	show: partition_device_type_read,
-};
+static DEVICE_ATTR(type,"type",S_IRUGO,partition_device_type_read,NULL);
 
 void driverfs_create_partitions(struct gendisk *hd, int minor)
 {
 	int pos = -1;
-	int devnum = minor >> hd->minor_shift;
+	int devnum = (minor - hd->first_minor) >> hd->minor_shift;
 	char dirname[256];
 	struct device *parent = 0;
 	int max_p;
 	int part;
 	devfs_handle_t dir = 0;
-	struct hd_struct *p = hd->part + minor;
+	struct hd_struct *p = hd->part + minor - hd->first_minor;
 	
 	/* get parent driverfs device structure */
 	if (hd->driverfs_dev_arr)
@@ -296,9 +290,9 @@
 			if (parent) current_driverfs_dev->bus = parent->bus;
 			device_register(current_driverfs_dev);
 			device_create_file(current_driverfs_dev,
-					&partition_device_type_file);
+					   &dev_attr_type);
 			device_create_file(current_driverfs_dev,
-					&partition_device_kdev_file);
+					   &dev_attr_kdev);
 		}
 	}
 }
@@ -308,7 +302,7 @@
 	int max_p;
 	int part;
 	struct device * current_driverfs_dev;
-	struct hd_struct *p = hd->part + minor;
+	struct hd_struct *p = hd->part + minor - hd->first_minor;
 	
 	max_p=(1 << hd->minor_shift);
 	
@@ -317,17 +311,17 @@
 		if ((p[part].nr_sects >= 1)) {
 			current_driverfs_dev = &p[part].hd_driverfs_dev;
 			device_remove_file(current_driverfs_dev,
-					partition_device_type_file.name);
+					   &dev_attr_type);
 			device_remove_file(current_driverfs_dev,
-					partition_device_kdev_file.name);
+					   &dev_attr_kdev);
 			put_device(current_driverfs_dev);	
 		}
 	}
 	current_driverfs_dev = &p->hd_driverfs_dev;
-	device_remove_file(current_driverfs_dev, 
-				partition_device_type_file.name);
-	device_remove_file(current_driverfs_dev, 
-				partition_device_kdev_file.name);
+	device_remove_file(current_driverfs_dev,
+			   &dev_attr_type);
+	device_remove_file(current_driverfs_dev,
+			   &dev_attr_kdev);
 	put_device(current_driverfs_dev);	
 	return;
 }
@@ -335,31 +329,17 @@
 static void check_partition(struct gendisk *hd, kdev_t dev)
 {
 	devfs_handle_t de = NULL;
-	unsigned long first_sector;
 	struct block_device *bdev;
 	char buf[64];
 	struct parsed_partitions *state;
 	int i;
 
-	first_sector = hd->part[minor(dev)].start_sect;
-
-	/*
-	 * This is a kludge to allow the partition check to be
-	 * skipped for specific drives (e.g. IDE CD-ROM drives)
-	 */
-	if ((int)first_sector == -1) {
-		hd->part[minor(dev)].start_sect = 0;
-		return;
-	}
-	if (first_sector != 0)
-		BUG();
-
 	state = kmalloc(sizeof(struct parsed_partitions), GFP_KERNEL);
 	if (!state)
 		return;
 
 	if (hd->de_arr)
-		de = hd->de_arr[minor(dev) >> hd->minor_shift];
+		de = hd->de_arr[(minor(dev)-hd->first_minor)>>hd->minor_shift];
 	i = devfs_generate_path (de, buf, sizeof buf);
 	if (i >= 0) {
 		printk(KERN_INFO " /dev/%s:", buf + i);
@@ -377,6 +357,7 @@
 	state->limit = 1<<hd->minor_shift;
 	for (i = 0; check_part[i]; i++) {
 		int res, j;
+		struct hd_struct *p;
 		memset(&state->parts, 0, sizeof(state->parts));
 		res = check_part[i](state, bdev);
 		if (!res)
@@ -385,12 +366,11 @@
 			if (warn_no_part)
 				printk(" unable to read partition table\n");
 			goto setup_devfs;
-		}
+		} 
+		p = hd->part + minor(dev) - hd->first_minor;
 		for (j = 1; j < state->limit; j++) {
-			hd->part[j + minor(dev)].start_sect =
-				state->parts[j].from;
-			hd->part[j + minor(dev)].nr_sects =
-				state->parts[j].size;
+			p[j].start_sect = state->parts[j].from;
+			p[j].nr_sects = state->parts[j].size;
 #if CONFIG_BLK_DEV_MD
 			if (!state->parts[j].flags)
 				continue;
@@ -404,34 +384,31 @@
 setup_devfs:
 	blkdev_put(bdev, BDEV_RAW);
 out:
-	/* Setup driverfs tree */
-	if (hd->sizes)
-		driverfs_create_partitions(hd, minor(dev));
-	else
-		driverfs_remove_partitions(hd, minor(dev));
-
-	devfs_register_partitions (hd, minor(dev), hd->sizes ? 0 : 1);
+	driverfs_create_partitions(hd, minor(dev));
+	devfs_register_partitions (hd, minor(dev), 0);
 }
 
 #ifdef CONFIG_DEVFS_FS
 static void devfs_register_partition (struct gendisk *dev, int minor, int part)
 {
-	int devnum = minor >> dev->minor_shift;
+	int devnum = (minor - dev->first_minor) >> dev->minor_shift;
 	devfs_handle_t dir;
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
+	struct hd_struct *p = dev->part + minor - dev->first_minor;
 	char devname[16];
 
-	if (dev->part[minor + part].de) return;
-	dir = devfs_get_parent (dev->part[minor].de);
-	if (!dir) return;
+	if (p[part].de)
+		return;
+	dir = devfs_get_parent(p[0].de);
+	if (!dir)
+		return;
 	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
 		devfs_flags |= DEVFS_FL_REMOVABLE;
 	sprintf (devname, "part%d", part);
-	dev->part[minor + part].de =
-	    devfs_register (dir, devname, devfs_flags,
-			    dev->major, minor + part,
-			    S_IFBLK | S_IRUSR | S_IWUSR,
-			    dev->fops, NULL);
+	p[part].de = devfs_register (dir, devname, devfs_flags,
+				    dev->major, minor + part,
+				    S_IFBLK | S_IRUSR | S_IWUSR,
+				    dev->fops, NULL);
 }
 
 static struct unique_numspace disc_numspace = UNIQUE_NUMBERSPACE_INITIALISER;
@@ -439,38 +416,40 @@
 static void devfs_register_disc (struct gendisk *dev, int minor)
 {
 	int pos = 0;
-	int devnum = minor >> dev->minor_shift;
+	int devnum = (minor - dev->first_minor) >> dev->minor_shift;
 	devfs_handle_t dir, slave;
 	unsigned int devfs_flags = DEVFS_FL_DEFAULT;
 	char dirname[64], symlink[16];
 	static devfs_handle_t devfs_handle;
+	struct hd_struct *p = dev->part + minor - dev->first_minor;
 
-	if (dev->part[minor].de) return;
+	if (p[0].de)
+		return;
 	if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
 		devfs_flags |= DEVFS_FL_REMOVABLE;
 	if (dev->de_arr) {
 		dir = dev->de_arr[devnum];
 		if (!dir)  /*  Aware driver wants to block disc management  */
 			return;
-		pos = devfs_generate_path (dir, dirname + 3, sizeof dirname-3);
-		if (pos < 0) return;
-		strncpy (dirname + pos, "../", 3);
-	}
-	else {
+		pos = devfs_generate_path(dir, dirname + 3, sizeof dirname-3);
+		if (pos < 0)
+			return;
+		strncpy(dirname + pos, "../", 3);
+	} else {
 		/*  Unaware driver: construct "real" directory  */
-		sprintf (dirname, "../%s/disc%d", dev->major_name, devnum);
-		dir = devfs_mk_dir (NULL, dirname + 3, NULL);
+		sprintf(dirname, "../%s/disc%d", dev->major_name,
+			(dev->first_minor >> dev->minor_shift) + devnum);
+		dir = devfs_mk_dir(NULL, dirname + 3, NULL);
 	}
 	if (!devfs_handle)
-		devfs_handle = devfs_mk_dir (NULL, "discs", NULL);
-	dev->part[minor].number = devfs_alloc_unique_number (&disc_numspace);
-	sprintf (symlink, "disc%d", dev->part[minor].number);
+		devfs_handle = devfs_mk_dir(NULL, "discs", NULL);
+	p[0].number = devfs_alloc_unique_number (&disc_numspace);
+	sprintf(symlink, "disc%d", p[0].number);
 	devfs_mk_symlink (devfs_handle, symlink, DEVFS_FL_DEFAULT,
 			  dirname + pos, &slave, NULL);
-	dev->part[minor].de =
-	    devfs_register (dir, "disc", devfs_flags, dev->major, minor,
+	p[0].de = devfs_register (dir, "disc", devfs_flags, dev->major, minor,
 			    S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
-	devfs_auto_unregister (dev->part[minor].de, slave);
+	devfs_auto_unregister(p[0].de, slave);
 	if (!dev->de_arr)
 		devfs_auto_unregister (slave, dir);
 }
@@ -480,23 +459,23 @@
 {
 #ifdef CONFIG_DEVFS_FS
 	int part, max_p;
+	struct hd_struct *p = dev->part + minor - dev->first_minor;
 
 	if (!unregister)
 		devfs_register_disc (dev, minor);
 	max_p = (1 << dev->minor_shift);
 	for (part = 1; part < max_p; part++) {
-		if ( unregister || (dev->part[part + minor].nr_sects < 1) ) {
-			devfs_unregister (dev->part[part + minor].de);
-			dev->part[part + minor].de = NULL;
+		if ( unregister || (p[part].nr_sects < 1) ) {
+			devfs_unregister(p[part].de);
+			dev->part[p].de = NULL;
 			continue;
 		}
 		devfs_register_partition (dev, minor, part);
 	}
 	if (unregister) {
-		devfs_unregister (dev->part[minor].de);
-		dev->part[minor].de = NULL;
-		devfs_dealloc_unique_number (&disc_numspace,
-					     dev->part[minor].number);
+		devfs_unregister(p[0].de);
+		p[0].de = NULL;
+		devfs_dealloc_unique_number(&disc_numspace, p[0].number);
 	}
 #endif  /*  CONFIG_DEVFS_FS  */
 }
@@ -521,8 +500,9 @@
 
 void grok_partitions(kdev_t dev, long size)
 {
-	int i, minors, first_minor, end_minor;
+	int minors, first_minor, end_minor;
 	struct gendisk *g = get_gendisk(dev);
+	struct hd_struct *p;
 
 	if (!g)
 		return;
@@ -536,36 +516,18 @@
 	}
 	end_minor = first_minor + minors;
  
-	if (!g->sizes)
-		blk_size[g->major] = NULL;
-
-	g->part[first_minor].nr_sects = size;
+	p = g->part + first_minor - g->first_minor;
+	p[0].nr_sects = size;
 
 	/* No minors to use for partitions */
 	if (minors == 1)
 		return;
 
-	if (g->sizes) {
-		g->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
-		for (i = first_minor + 1; i < end_minor; i++)
-			g->sizes[i] = 0;
-	}
-	blk_size[g->major] = g->sizes;
-
 	/* No such device (e.g., media were just removed) */
 	if (!size)
 		return;
 
 	check_partition(g, mk_kdev(g->major, first_minor));
-
- 	/*
- 	 * We need to set the sizes array before we will be able to access
- 	 * any of the partitions on this device.
- 	 */
-	if (g->sizes != NULL) {	/* optional safeguard in ll_rw_blk.c */
-		for (i = first_minor; i < end_minor; i++)
-			g->sizes[i] = g->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
-	}
 }
 
 unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
@@ -596,6 +558,7 @@
 	struct gendisk *g;
 	kdev_t devp;
 	int p, major, minor, minor0, max_p, res;
+	struct hd_struct *part;
 
 	g = get_gendisk(dev);
 	if (g == NULL)
@@ -608,19 +571,20 @@
 	if (minor0 != minor)		/* for now only whole-disk reread */
 		return -EINVAL;		/* %%% later.. */
 
+	part = g->part + minor - g->first_minor;
 	/* invalidate stuff */
 	for (p = max_p - 1; p >= 0; p--) {
 		minor = minor0 + p;
 		devp = mk_kdev(major,minor);
 #if 0					/* %%% superfluous? */
-		if (g->part[minor].nr_sects == 0)
+		if (part[p].nr_sects == 0)
 			continue;
 #endif
 		res = invalidate_device(devp, 1);
 		if (res)
 			return res;
-		g->part[minor].start_sect = 0;
-		g->part[minor].nr_sects = 0;
+		part[p].start_sect = 0;
+		part[p].nr_sects = 0;
 	}
 	return 0;
 }
diff -Nru a/fs/partitions/msdos.c b/fs/partitions/msdos.c
--- a/fs/partitions/msdos.c	Thu Aug  1 14:17:36 2002
+++ b/fs/partitions/msdos.c	Thu Aug  1 14:17:36 2002
@@ -385,87 +385,6 @@
 	{SOLARIS_X86_PARTITION, parse_solaris_x86},
 	{0, NULL},
 };
-/*
- * Look for various forms of IDE disk geometry translation
- */
-static int handle_ide_mess(struct block_device *bdev)
-{
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-	Sector sect;
-	unsigned char *data;
-	kdev_t dev = to_kdev_t(bdev->bd_dev);
-	unsigned int sig;
-	int heads = 0;
-	struct partition *p;
-	int i;
-#ifdef CONFIG_BLK_DEV_IDE_MODULE
-	if (!ide_xlate_1024)
-		return 1;
-#endif
-	/*
-	 * The i386 partition handling programs very often
-	 * make partitions end on cylinder boundaries.
-	 * There is no need to do so, and Linux fdisk doesn't always
-	 * do this, and Windows NT on Alpha doesn't do this either,
-	 * but still, this helps to guess #heads.
-	 */
-	data = read_dev_sector(bdev, 0, &sect);
-	if (!data)
-		return -1;
-	if (!msdos_magic_present(data + 510)) {
-		put_dev_sector(sect);
-		return 0;
-	}
-	sig = le16_to_cpu(*(unsigned short *)(data + 2));
-	p = (struct partition *) (data + 0x1be);
-	for (i = 0; i < 4; i++) {
-		struct partition *q = &p[i];
-		if (NR_SECTS(q)) {
-			if ((q->sector & 63) == 1 &&
-			    (q->end_sector & 63) == 63)
-				heads = q->end_head + 1;
-			break;
-		}
-	}
-	if (SYS_IND(p) == EZD_PARTITION) {
-		/*
-		 * Accesses to sector 0 must go to sector 1 instead.
-		 */
-		if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
-			goto reread;
-	} else if (SYS_IND(p) == DM6_PARTITION) {
-
-		/*
-		 * Everything on the disk is offset by 63 sectors,
-		 * including a "new" MBR with its own partition table.
-		 */
-		if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
-			goto reread;
-	} else if (sig <= 0x1ae &&
-		   data[sig] == 0xAA && data[sig+1] == 0x55 &&
-		   (data[sig+2] & 1)) {
-		/* DM6 signature in MBR, courtesy of OnTrack */
-		(void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
-	} else if (SYS_IND(p) == DM6_AUX1PARTITION ||
-		   SYS_IND(p) == DM6_AUX3PARTITION) {
-		/*
-		 * DM6 on other than the first (boot) drive
-		 */
-		(void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
-	} else {
-		(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
-	}
-	put_dev_sector(sect);
-	return 1;
-
-reread:
-	put_dev_sector(sect);
-	/* Flush the cache */
-	invalidate_bdev(bdev, 1);
-	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-	return 1;
-}
  
 int msdos_partition(struct parsed_partitions *state, struct block_device *bdev)
 {
@@ -474,11 +393,7 @@
 	unsigned char *data;
 	struct partition *p;
 	int slot;
-	int err;
 
-	err = handle_ide_mess(bdev);
-	if (err <= 0)
-		return err;
 	data = read_dev_sector(bdev, 0, &sect);
 	if (!data)
 		return -1;
@@ -524,21 +439,6 @@
 			state->parts[slot].flags = 1;
 	}
 
-	/*
-	 *  Check for old-style Disk Manager partition table
-	 */
-	if (msdos_magic_present(data + 0xfc)) {
-		p = (struct partition *) (0x1be + data);
-		for (slot = 4 ; slot < 16 ; slot++, state->next++) {
-			p--;
-			if (state->next == state->limit)
-				break;
-			if (!(START_SECT(p) && NR_SECTS(p)))
-				continue;
-			put_partition(state, state->next,
-						START_SECT(p), NR_SECTS(p));
-		}
-	}
 	printk("\n");
 
 	/* second pass - output for each on a separate line */
@@ -556,7 +456,7 @@
 		if (!subtypes[n].parse)
 			continue;
 		subtypes[n].parse(state, bdev, START_SECT(p)*sector_size,
-						NR_SECTS(p)*sector_size, n);
+						NR_SECTS(p)*sector_size, slot);
 	}
 	put_dev_sector(sect);
 	return 1;
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Thu Aug  1 14:17:36 2002
+++ b/fs/proc/proc_misc.c	Thu Aug  1 14:17:36 2002
@@ -126,11 +126,13 @@
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
+extern atomic_t vm_committed_space;
+
 static int meminfo_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
 	struct sysinfo i;
-	int len;
+	int len, committed;
 	struct page_state ps;
 
 	get_page_state(&ps);
@@ -140,6 +142,7 @@
 #define K(x) ((x) << (PAGE_SHIFT - 10))
 	si_meminfo(&i);
 	si_swapinfo(&i);
+	committed = atomic_read(&vm_committed_space);
 
 	/*
 	 * Tagged format, for easy grepping and expansion.
@@ -160,9 +163,9 @@
 		"SwapFree:     %8lu kB\n"
 		"Dirty:        %8lu kB\n"
 		"Writeback:    %8lu kB\n"
+		"Committed_AS: %8u kB\n"
 		"PageTables:   %8lu kB\n"
-		"PteChainTot:  %8lu kB\n"
-		"PteChainUsed: %8lu kB\n",
+		"ReverseMaps:  %8lu\n",
 		K(i.totalram),
 		K(i.freeram),
 		K(i.sharedram),
@@ -178,9 +181,9 @@
 		K(i.freeswap),
 		K(ps.nr_dirty),
 		K(ps.nr_writeback),
+		K(committed),
 		K(ps.nr_page_table_pages),
-		K(ps.nr_pte_chain_pages),
-		ps.used_pte_chains_bytes >> 10
+		ps.nr_reverse_maps
 		);
 
 	return proc_calc_metrics(page, start, off, count, eof, len);
diff -Nru a/fs/qnx4/file.c b/fs/qnx4/file.c
--- a/fs/qnx4/file.c	Thu Aug  1 14:17:40 2002
+++ b/fs/qnx4/file.c	Thu Aug  1 14:17:40 2002
@@ -33,6 +33,7 @@
 #ifdef CONFIG_QNX4FS_RW
 	fsync:			qnx4_sync_file,
 #endif
+	sendfile:		generic_file_sendfile,
 };
 
 struct inode_operations qnx4_file_inode_operations =
diff -Nru a/fs/ramfs/inode.c b/fs/ramfs/inode.c
--- a/fs/ramfs/inode.c	Thu Aug  1 14:17:40 2002
+++ b/fs/ramfs/inode.c	Thu Aug  1 14:17:40 2002
@@ -276,6 +276,7 @@
 	write:		generic_file_write,
 	mmap:		generic_file_mmap,
 	fsync:		ramfs_sync_file,
+	sendfile:	generic_file_sendfile,
 };
 
 static struct inode_operations ramfs_dir_inode_operations = {
diff -Nru a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c	Thu Aug  1 14:17:41 2002
+++ b/fs/read_write.c	Thu Aug  1 14:17:41 2002
@@ -19,6 +19,7 @@
 	llseek:		generic_file_llseek,
 	read:		generic_file_read,
 	mmap:		generic_file_mmap,
+	sendfile:	generic_file_sendfile,
 };
 
 loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
@@ -184,8 +185,6 @@
 		return -EBADF;
 	if (!file->f_op || !file->f_op->read)
 		return -EINVAL;
-	if (pos < 0)
-		return -EINVAL;
 
 	ret = locks_verify_area(FLOCK_VERIFY_READ, inode, file, *pos, count);
 	if (!ret) {
@@ -209,8 +208,6 @@
 		return -EBADF;
 	if (!file->f_op || !file->f_op->write)
 		return -EINVAL;
-	if (pos < 0)
-		return -EINVAL;
 
 	ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, *pos, count);
 	if (!ret) {
@@ -253,12 +250,15 @@
 	return ret;
 }
 
-asmlinkage ssize_t sys_pread(unsigned int fd, char *buf,
+asmlinkage ssize_t sys_pread64(unsigned int fd, char *buf,
 			     size_t count, loff_t pos)
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
 
+	if (pos < 0)
+		return -EINVAL;
+
 	file = fget(fd);
 	if (file) {
 		ret = vfs_read(file, buf, count, &pos);
@@ -268,12 +268,15 @@
 	return ret;
 }
 
-asmlinkage ssize_t sys_pwrite(unsigned int fd, const char *buf,
+asmlinkage ssize_t sys_pwrite64(unsigned int fd, const char *buf,
 			      size_t count, loff_t pos)
 {
 	struct file *file;
 	ssize_t ret = -EBADF;
 
+	if (pos < 0)
+		return -EINVAL;
+
 	file = fget(fd);
 	if (file) {
 		ret = vfs_write(file, buf, count, &pos);
@@ -435,4 +438,114 @@
 
 bad_file:
 	return ret;
+}
+
+static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
+			   size_t count, loff_t max)
+{
+	struct file * in_file, * out_file;
+	struct inode * in_inode, * out_inode;
+	loff_t pos;
+	ssize_t retval;
+
+	/*
+	 * Get input file, and verify that it is ok..
+	 */
+	retval = -EBADF;
+	in_file = fget(in_fd);
+	if (!in_file)
+		goto out;
+	if (!(in_file->f_mode & FMODE_READ))
+		goto fput_in;
+	retval = -EINVAL;
+	in_inode = in_file->f_dentry->d_inode;
+	if (!in_inode)
+		goto fput_in;
+	if (!in_file->f_op || !in_file->f_op->sendfile)
+		goto fput_in;
+	retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count);
+	if (retval)
+		goto fput_in;
+
+	/*
+	 * Get output file, and verify that it is ok..
+	 */
+	retval = -EBADF;
+	out_file = fget(out_fd);
+	if (!out_file)
+		goto fput_in;
+	if (!(out_file->f_mode & FMODE_WRITE))
+		goto fput_out;
+	retval = -EINVAL;
+	if (!out_file->f_op || !out_file->f_op->sendpage)
+		goto fput_out;
+	out_inode = out_file->f_dentry->d_inode;
+	retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count);
+	if (retval)
+		goto fput_out;
+
+	if (!ppos)
+		ppos = &in_file->f_pos;
+
+	if (!max)
+		max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
+
+	pos = *ppos;
+	retval = -EINVAL;
+	if (unlikely(pos < 0))
+		goto fput_out;
+	if (unlikely(pos + count > max)) {
+		retval = -EOVERFLOW;
+		if (pos >= max)
+			goto fput_out;
+		count = max - pos;
+	}
+
+	retval = in_file->f_op->sendfile(out_file, in_file, ppos, count);
+
+	if (*ppos > max)
+		retval = -EOVERFLOW;
+
+fput_out:
+	fput(out_file);
+fput_in:
+	fput(in_file);
+out:
+	return retval;
+}
+
+asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
+{
+	loff_t pos;
+	off_t off;
+	ssize_t ret;
+
+	if (offset) {
+		if (unlikely(get_user(off, offset)))
+			return -EFAULT;
+		pos = off;
+		ret = do_sendfile(out_fd, in_fd, &pos, count, MAX_NON_LFS);
+		if (unlikely(put_user(pos, offset)))
+			return -EFAULT;
+		return ret;
+	}
+
+	return do_sendfile(out_fd, in_fd, NULL, count, MAX_NON_LFS);
+}
+
+asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count)
+{
+	loff_t pos;
+	ssize_t ret;
+
+	if (offset) {
+		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
+			return -EFAULT;
+		ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
+		if (unlikely(put_user(pos, offset)))
+			return -EFAULT;
+		return ret;
+	}
+
+	return do_sendfile(out_fd, in_fd, NULL, count, 0);
 }
diff -Nru a/fs/reiserfs/file.c b/fs/reiserfs/file.c
--- a/fs/reiserfs/file.c	Thu Aug  1 14:17:36 2002
+++ b/fs/reiserfs/file.c	Thu Aug  1 14:17:36 2002
@@ -147,6 +147,7 @@
     mmap:	generic_file_mmap,
     release:	reiserfs_file_release,
     fsync:	reiserfs_sync_file,
+    sendfile:	generic_file_sendfile,
 };
 
 
diff -Nru a/fs/smbfs/file.c b/fs/smbfs/file.c
--- a/fs/smbfs/file.c	Thu Aug  1 14:17:41 2002
+++ b/fs/smbfs/file.c	Thu Aug  1 14:17:41 2002
@@ -105,9 +105,9 @@
 	int		error;
 	struct dentry  *dentry = file->f_dentry;
 
-	get_page(page);
+	page_cache_get(page);
 	error = smb_readpage_sync(dentry, page);
-	put_page(page);
+	page_cache_release(page);
 	return error;
 }
 
@@ -194,11 +194,11 @@
 	if (page->index >= end_index+1 || !offset)
 		return -EIO;
 do_it:
-	get_page(page);
+	page_cache_get(page);
 	err = smb_writepage_sync(inode, page, 0, offset);
 	SetPageUptodate(page);
 	unlock_page(page);
-	put_page(page);
+	page_cache_release(page);
 	return err;
 }
 
diff -Nru a/fs/smbfs/smbiod.c b/fs/smbfs/smbiod.c
--- a/fs/smbfs/smbiod.c	Thu Aug  1 14:17:41 2002
+++ b/fs/smbfs/smbiod.c	Thu Aug  1 14:17:41 2002
@@ -269,6 +269,7 @@
 		set_bit(SMBIOD_DATA_READY, &smbiod_flags);
 
 out:
+	return;
 }
 
 /*
diff -Nru a/fs/sysv/file.c b/fs/sysv/file.c
--- a/fs/sysv/file.c	Thu Aug  1 14:17:41 2002
+++ b/fs/sysv/file.c	Thu Aug  1 14:17:41 2002
@@ -25,6 +25,7 @@
 	write:		generic_file_write,
 	mmap:		generic_file_mmap,
 	fsync:		sysv_sync_file,
+	sendfile:	generic_file_sendfile,
 };
 
 struct inode_operations sysv_file_inode_operations = {
diff -Nru a/fs/udf/file.c b/fs/udf/file.c
--- a/fs/udf/file.c	Thu Aug  1 14:17:36 2002
+++ b/fs/udf/file.c	Thu Aug  1 14:17:36 2002
@@ -365,6 +365,7 @@
 	write:			udf_file_write,
 	release:		udf_release_file,
 	fsync:			udf_fsync_file,
+	sendfile:		generic_file_sendfile,
 };
 
 struct inode_operations udf_file_inode_operations = {
diff -Nru a/fs/ufs/file.c b/fs/ufs/file.c
--- a/fs/ufs/file.c	Thu Aug  1 14:17:39 2002
+++ b/fs/ufs/file.c	Thu Aug  1 14:17:39 2002
@@ -47,6 +47,7 @@
 	write:		generic_file_write,
 	mmap:		generic_file_mmap,
 	open:           generic_file_open,
+	sendfile:	generic_file_sendfile,
 };
 
 struct inode_operations ufs_file_inode_operations = {
diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c
--- a/fs/ufs/super.c	Thu Aug  1 14:17:36 2002
+++ b/fs/ufs/super.c	Thu Aug  1 14:17:36 2002
@@ -673,7 +673,7 @@
 	}
 	if (uspi->s_bsize < 4096) {
 		printk("ufs_read_super: block size %u is too small\n",
-			uspi->s_fsize);
+			uspi->s_bsize);
 		goto failed;
 	}
 	if (uspi->s_bsize / uspi->s_fsize > 8) {
diff -Nru a/include/asm-alpha/processor.h b/include/asm-alpha/processor.h
--- a/include/asm-alpha/processor.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-alpha/processor.h	Thu Aug  1 14:17:41 2002
@@ -74,7 +74,7 @@
 #define KSTK_ESP(tsk) \
   ((tsk) == current ? rdusp() : (tsk)->thread_info->pcb.usp)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 #define ARCH_HAS_PREFETCH
 #define ARCH_HAS_PREFETCHW
diff -Nru a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
--- a/include/asm-alpha/socket.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-alpha/socket.h	Thu Aug  1 14:17:41 2002
@@ -3,7 +3,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 /*
  * Note: we only bother about making the SOL_SOCKET options
  * same as OSF/1, as that's all that "normal" programs are
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-alpha/unistd.h	Thu Aug  1 14:17:40 2002
@@ -286,8 +286,8 @@
 #define __NR_pciconfig_write		346
 #define __NR_query_module		347
 #define __NR_prctl			348
-#define __NR_pread			349
-#define __NR_pwrite			350
+#define __NR_pread64			349
+#define __NR_pwrite64			350
 #define __NR_rt_sigreturn		351
 #define __NR_rt_sigaction		352
 #define __NR_rt_sigprocmask		353
diff -Nru a/include/asm-arm/arch-ebsa285/keyboard.h b/include/asm-arm/arch-ebsa285/keyboard.h
--- a/include/asm-arm/arch-ebsa285/keyboard.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-arm/arch-ebsa285/keyboard.h	Thu Aug  1 14:17:40 2002
@@ -6,63 +6,4 @@
  * Copyright (C) 1998-2001 Russell King
  * (C) 1998 Phil Blundell
  */
-#include <linux/config.h>
-#include <linux/ioport.h>
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#define KEYBOARD_IRQ		IRQ_ISA_KEYBOARD
-#define NR_SCANCODES		128
-
-#define kbd_disable_irq()	do { } while (0)
-#define kbd_enable_irq()	do { } while (0)
-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
-			   char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[128];
-
-static inline void kbd_init_hw(void)
-{
-	if (have_isa_bridge) {
-		k_setkeycode    = pckbd_setkeycode;
-		k_getkeycode    = pckbd_getkeycode;
-		k_translate     = pckbd_translate;
-		k_unexpected_up = pckbd_unexpected_up;
-		k_leds          = pckbd_leds;
-#ifdef CONFIG_MAGIC_SYSRQ
-		k_sysrq_key     = 0x54;
-		k_sysrq_xlate   = pckbd_sysrq_xlate;
-#endif
-		pckbd_init_hw();
-	}
-}
-
-
-/*
- * The rest of this file is to do with supporting pc_keyb.c
- */
-
-/* resource allocation */
-#define kbd_request_region()	request_region(0x60, 16, "keyboard")
-#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \
-					     "keyboard", NULL)
-
-/* How to access the keyboard macros on this platform.  */
-#define kbd_read_input() inb(KBD_DATA_REG)
-#define kbd_read_status() inb(KBD_STATUS_REG)
-#define kbd_write_output(val) outb(val, KBD_DATA_REG)
-#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
-
-/* Some stoneage hardware needs delays after some operations.  */
-#define kbd_pause() do { } while(0)
-
-#define aux_request_irq(hand, dev_id)					\
-	request_irq(AUX_IRQ, hand, SA_SHIRQ, "PS/2 Mouse", dev_id)
-
-#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id)
-
+#define kbd_init_hw()		do { } while (0)
diff -Nru a/include/asm-arm/arch-integrator/keyboard.h b/include/asm-arm/arch-integrator/keyboard.h
--- a/include/asm-arm/arch-integrator/keyboard.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/arch-integrator/keyboard.h	Thu Aug  1 14:17:40 2002
@@ -17,13 +17,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *  Keyboard driver definitions for the Integrator architecture
+ *  Now using the input subsystem...
  */
-#include <asm/irq.h>
-
-#define NR_SCANCODES 128
-
-extern int kmi_kbd_init(void);
-
-#define kbd_disable_irq()	disable_irq(IRQ_KMIINT0)
-#define kbd_enable_irq()	enable_irq(IRQ_KMIINT0)
-#define kbd_init_hw()		kmi_kbd_init()
+#define kbd_init_hw()		do { } while (0)
diff -Nru a/include/asm-arm/arch-rpc/keyboard.h b/include/asm-arm/arch-rpc/keyboard.h
--- a/include/asm-arm/arch-rpc/keyboard.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/arch-rpc/keyboard.h	Thu Aug  1 14:17:40 2002
@@ -8,13 +8,6 @@
  * published by the Free Software Foundation.
  *
  *  Keyboard driver definitions for RiscPC architecture
+ *  Now using the input subsystem...
  */
-#include <asm/irq.h>
-
-#define NR_SCANCODES 128
-
-extern int ps2kbd_init_hw(void);
-
-#define kbd_disable_irq()	disable_irq(IRQ_KEYBOARDRX)
-#define kbd_enable_irq()	enable_irq(IRQ_KEYBOARDRX)
-#define kbd_init_hw()		ps2kbd_init_hw()
+#define kbd_init_hw()		do { } while (0)
diff -Nru a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h
--- a/include/asm-arm/arch-sa1100/hardware.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/arch-sa1100/hardware.h	Thu Aug  1 14:17:40 2002
@@ -13,8 +13,6 @@
 #define __ASM_ARCH_HARDWARE_H
 
 #include <linux/config.h>
-#include <asm/mach-types.h>
-
 
 /* Flushing areas */
 #define FLUSH_BASE_PHYS		0xe0000000	/* SA1100 zero bank */
diff -Nru a/include/asm-arm/arch-sa1100/keyboard.h b/include/asm-arm/arch-sa1100/keyboard.h
--- a/include/asm-arm/arch-sa1100/keyboard.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/arch-sa1100/keyboard.h	Thu Aug  1 14:17:40 2002
@@ -8,21 +8,13 @@
 
 #include <linux/config.h>
 #include <asm/mach-types.h>
-#include <asm/arch/assabet.h>
 
-#define kbd_disable_irq()	do { } while(0)
-#define kbd_enable_irq()	do { } while(0)
-
-extern int sa1111_kbd_init_hw(void);
 extern void gc_kbd_init_hw(void);
 extern void smartio_kbd_init_hw(void);
 extern void cerf_kbd_init_hw(void);
 
 static inline void kbd_init_hw(void)
 {
-	if ((machine_is_assabet() && machine_has_neponset()) ||
-	    machine_is_graphicsmaster())
-		sa1111_kbd_init_hw();
 	if (machine_is_graphicsclient())
 		gc_kbd_init_hw();
 	if (machine_is_adsbitsy())
@@ -30,11 +22,6 @@
 #ifdef CONFIG_SA1100_CERF_CPLD
 	if (machine_is_cerf())
 		cerf_kbd_init_hw();
-#endif
-#ifdef CONFIG_SA1100_PT_SYSTEM3
-	/* TODO: add system 3 board specific functions here */
-	if (machine_is_pt_system3())
-		sa1111_kbd_init_hw();
 #endif
 }
 
diff -Nru a/include/asm-arm/atomic.h b/include/asm-arm/atomic.h
--- a/include/asm-arm/atomic.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-arm/atomic.h	Thu Aug  1 14:17:36 2002
@@ -36,7 +36,7 @@
 {
 	unsigned long flags;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	v->counter += i;
 	local_irq_restore(flags);
 }
@@ -45,7 +45,7 @@
 {
 	unsigned long flags;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	v->counter -= i;
 	local_irq_restore(flags);
 }
@@ -54,7 +54,7 @@
 {
 	unsigned long flags;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	v->counter += 1;
 	local_irq_restore(flags);
 }
@@ -63,7 +63,7 @@
 {
 	unsigned long flags;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	v->counter -= 1;
 	local_irq_restore(flags);
 }
@@ -73,7 +73,7 @@
 	unsigned long flags;
 	int val;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	val = v->counter;
 	v->counter = val -= 1;
 	local_irq_restore(flags);
@@ -86,7 +86,7 @@
 	unsigned long flags;
 	int val;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	val = v->counter;
 	v->counter = val += i;
 	local_irq_restore(flags);
@@ -98,7 +98,7 @@
 {
 	unsigned long flags;
 
-	local_save_flags_cli(flags);
+	local_irq_save(flags);
 	*addr &= ~mask;
 	local_irq_restore(flags);
 }
diff -Nru a/include/asm-arm/hardirq.h b/include/asm-arm/hardirq.h
--- a/include/asm-arm/hardirq.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/hardirq.h	Thu Aug  1 14:17:40 2002
@@ -17,27 +17,70 @@
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
 /*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
+ * We put the hardirq and softirq counter into the preemption
+ * counter.  The bitmask has the following meaning:
+ *
+ * - bits 0-7 are the preemption count (max depth: 256)
+ * - bits 8-15 are the softirq count (max # of softirqs: 256)
+ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ * - bit 26 is the PREEMPT_ACTIVE flag
  */
-#define in_interrupt() ({ const int __cpu = smp_processor_id(); \
-	(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
-
-#define in_irq() (local_irq_count(smp_processor_id()) != 0)
-
-#ifndef CONFIG_SMP
+#define PREEMPT_BITS	8
+#define SOFTIRQ_BITS	8
+#define HARDIRQ_BITS	8
+
+#define PREEMPT_SHIFT	0
+#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
+#define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
+
+#define __MASK(x)	((1UL << (x))-1)
+
+#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
+#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
+#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+
+#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
+#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
+#define irq_count()	(preempt_count() & (HARDIRQ_MASK|SOFTIRQ_MASK))
+
+#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
+#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
+#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
+
+/*
+ * The hardirq mask has to be large enough to have space
+ * for potentially all IRQ sources in the system nesting
+ * on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
+
+/*
+ * Are we doing bottom half or hardware interrupt processing?
+ * Are we in a softirq context? Interrupt context?
+ */
+#define in_irq()		(hardirq_count())
+#define in_softirq()		(softirq_count())
+#define in_interrupt()		(irq_count())
 
-#define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
-#define hardirq_endlock(cpu)	do { } while (0)
+#define hardirq_trylock()	(!in_interrupt())
+#define hardirq_endlock()	do { } while (0)
 
-#define irq_enter(cpu,irq)	(local_irq_count(cpu)++)
-#define irq_exit(cpu,irq)	(local_irq_count(cpu)--)
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-#define synchronize_irq()	do { } while (0)
-#define release_irqlock(cpu)	do { } while (0)
+#ifndef CONFIG_SMP
+#define irq_exit()							\
+	do {								\
+		preempt_count() -= HARDIRQ_OFFSET;			\
+		if (!in_interrupt() && softirq_pending(smp_processor_id())) \
+			__asm__("bl%? __do_softirq": : : "lr");/* out of line */\
+		preempt_enable_no_resched();				\
+	} while (0)
 
+#define synchronize_irq(irq)	barrier()
 #else
 #error SMP not supported
-#endif /* CONFIG_SMP */
+#endif
 
 #endif /* __ASM_HARDIRQ_H */
diff -Nru a/include/asm-arm/hardware/sa1111.h b/include/asm-arm/hardware/sa1111.h
--- a/include/asm-arm/hardware/sa1111.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/hardware/sa1111.h	Thu Aug  1 14:17:40 2002
@@ -529,120 +529,31 @@
  *
  */
 
-#define _KBD( x )   _SA1111( 0x0A00 )
-#define _MSE( x )   _SA1111( 0x0C00 )
+#define SA1111_KBD		0x0a00
+#define SA1111_MSE		0x0c00
 
-#define _KBDCR	    _SA1111( 0x0A00 )
-#define _KBDSTAT    _SA1111( 0x0A04 )
-#define _KBDDATA    _SA1111( 0x0A08 )
-#define _KBDCLKDIV  _SA1111( 0x0A0C )
-#define _KBDPRECNT  _SA1111( 0x0A10 )
-#define _MSECR	    _SA1111( 0x0C00 )
-#define _MSESTAT    _SA1111( 0x0C04 )
-#define _MSEDATA    _SA1111( 0x0C08 )
-#define _MSECLKDIV  _SA1111( 0x0C0C )
-#define _MSEPRECNT  _SA1111( 0x0C10 )
-
-#if ( LANGUAGE == C )
-
-#define KBDCR		__CCREG(0x0a00)
-#define KBDSTAT		__CCREG(0x0a04)
-#define KBDDATA		__CCREG(0x0a08)
-#define KBDCLKDIV	__CCREG(0x0a0c)
-#define KBDPRECNT	__CCREG(0x0a10)
-#define MSECR		__CCREG(0x0c00)
-#define MSESTAT		__CCREG(0x0c04)
-#define MSEDATA		__CCREG(0x0c08)
-#define MSECLKDIV	__CCREG(0x0c0c)
-#define MSEPRECNT	__CCREG(0x0c10)
-
-#define KBDCR_ENA        0x08
-#define KBDCR_FKD        0x02
-#define KBDCR_FKC        0x01
-
-#define KBDSTAT_TXE      0x80
-#define KBDSTAT_TXB      0x40
-#define KBDSTAT_RXF      0x20
-#define KBDSTAT_RXB      0x10
-#define KBDSTAT_ENA      0x08
-#define KBDSTAT_RXP      0x04
-#define KBDSTAT_KBD      0x02
-#define KBDSTAT_KBC      0x01
-
-#define KBDCLKDIV_DivVal     Fld(4,0)
-
-#define MSECR_ENA        0x08
-#define MSECR_FKD        0x02
-#define MSECR_FKC        0x01
-
-#define MSESTAT_TXE      0x80
-#define MSESTAT_TXB      0x40
-#define MSESTAT_RXF      0x20
-#define MSESTAT_RXB      0x10
-#define MSESTAT_ENA      0x08
-#define MSESTAT_RXP      0x04
-#define MSESTAT_MSD      0x02
-#define MSESTAT_MSC      0x01
-
-#define MSECLKDIV_DivVal     Fld(4,0)
-
-#define KBDTEST1_CD      0x80
-#define KBDTEST1_RC1         0x40
-#define KBDTEST1_MC      0x20
-#define KBDTEST1_C       Fld(2,3)
-#define KBDTEST1_T2      0x40
-#define KBDTEST1_T1      0x20
-#define KBDTEST1_T0      0x10
-#define KBDTEST2_TICBnRES    0x08
-#define KBDTEST2_RKC         0x04
-#define KBDTEST2_RKD         0x02
-#define KBDTEST2_SEL         0x01
-#define KBDTEST3_ms_16       0x80
-#define KBDTEST3_us_64       0x40
-#define KBDTEST3_us_16       0x20
-#define KBDTEST3_DIV8        0x10
-#define KBDTEST3_DIn         0x08
-#define KBDTEST3_CIn         0x04
-#define KBDTEST3_KD      0x02
-#define KBDTEST3_KC      0x01
-#define KBDTEST4_BC12        0x80
-#define KBDTEST4_BC11        0x40
-#define KBDTEST4_TRES        0x20
-#define KBDTEST4_CLKOE       0x10
-#define KBDTEST4_CRES        0x08
-#define KBDTEST4_RXB         0x04
-#define KBDTEST4_TXB         0x02
-#define KBDTEST4_SRX         0x01
-
-#define MSETEST1_CD      0x80
-#define MSETEST1_RC1         0x40
-#define MSETEST1_MC      0x20
-#define MSETEST1_C       Fld(2,3)
-#define MSETEST1_T2      0x40
-#define MSETEST1_T1      0x20
-#define MSETEST1_T0      0x10
-#define MSETEST2_TICBnRES    0x08
-#define MSETEST2_RKC         0x04
-#define MSETEST2_RKD         0x02
-#define MSETEST2_SEL         0x01
-#define MSETEST3_ms_16       0x80
-#define MSETEST3_us_64       0x40
-#define MSETEST3_us_16       0x20
-#define MSETEST3_DIV8        0x10
-#define MSETEST3_DIn         0x08
-#define MSETEST3_CIn         0x04
-#define MSETEST3_KD      0x02
-#define MSETEST3_KC      0x01
-#define MSETEST4_BC12        0x80
-#define MSETEST4_BC11        0x40
-#define MSETEST4_TRES        0x20
-#define MSETEST4_CLKOE       0x10
-#define MSETEST4_CRES        0x08
-#define MSETEST4_RXB         0x04
-#define MSETEST4_TXB         0x02
-#define MSETEST4_SRX         0x01
-
-#endif  /* LANGUAGE == C */
+/*
+ * These are offsets from the above bases.
+ */
+#define SA1111_PS2CR		0x0000
+#define SA1111_PS2STAT		0x0004
+#define SA1111_PS2DATA		0x0008
+#define SA1111_PS2CLKDIV	0x000c
+#define SA1111_PS2PRECNT	0x0010
+
+#define PS2CR_ENA		0x08
+#define PS2CR_FKD		0x02
+#define PS2CR_FKC		0x01
+
+#define PS2STAT_STP		0x0100
+#define PS2STAT_TXE		0x0080
+#define PS2STAT_TXB		0x0040
+#define PS2STAT_RXF		0x0020
+#define PS2STAT_RXB		0x0010
+#define PS2STAT_ENA		0x0008
+#define PS2STAT_RXP		0x0004
+#define PS2STAT_KBD		0x0002
+#define PS2STAT_KBC		0x0001
 
 /*
  * PCMCIA Interface
diff -Nru a/include/asm-arm/io.h b/include/asm-arm/io.h
--- a/include/asm-arm/io.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/io.h	Thu Aug  1 14:17:40 2002
@@ -29,6 +29,13 @@
 #include <asm/arch/hardware.h>
 
 /*
+ * ISA I/O bus memory addresses are 1:1 with the physical address.
+ */
+#define isa_virt_to_bus virt_to_phys
+#define isa_page_to_bus page_to_phys
+#define isa_bus_to_virt phys_to_virt
+
+/*
  * Generic IO read/write.  These perform native-endian accesses.  Note
  * that some architectures will want to re-define __raw_{read,write}w.
  */
diff -Nru a/include/asm-arm/proc-armv/rmap.h b/include/asm-arm/proc-armv/rmap.h
--- a/include/asm-arm/proc-armv/rmap.h	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,51 +0,0 @@
-#ifndef _ARMV_RMAP_H
-#define _ARMV_RMAP_H
-/*
- * linux/include/asm-arm/proc-armv/rmap.h
- *
- * Architecture dependant parts of the reverse mapping code,
- *
- * ARM is different since hardware page tables are smaller than
- * the page size and Linux uses a "duplicate" one with extra info.
- * For rmap this means that the first 2 kB of a page are the hardware
- * page tables and the last 2 kB are the software page tables.
- */
-
-static inline void pgtable_add_rmap(pte_t * ptep, struct mm_struct * mm, unsigned long address)
-{
-	struct page * page = virt_to_page(ptep);
-
-	page->mm = mm;
-	page->index = address & ~((PTRS_PER_PTE * PAGE_SIZE) - 1);
-	inc_page_state(nr_page_table_pages);
-}
-
-static inline void pgtable_remove_rmap(pte_t * ptep)
-{
-	struct page * page = virt_to_page(ptep);
-
-	page->mm = NULL;
-	page->index = 0;
-	dec_page_state(nr_page_table_pages);
-}
-
-static inline struct mm_struct * ptep_to_mm(pte_t * ptep)
-{
-	struct page * page = virt_to_page(ptep);
-
-	return page->mm;
-}
-
-/* The page table takes half of the page */
-#define PTE_MASK  ((PAGE_SIZE / 2) - 1)
-
-static inline unsigned long ptep_to_address(pte_t * ptep)
-{
-	struct page * page = virt_to_page(ptep);
-	unsigned long low_bits;
-
-	low_bits = ((unsigned long)ptep & PTE_MASK) * PTRS_PER_PTE;
-	return page->index + low_bits;
-}
-
-#endif /* _ARMV_RMAP_H */
diff -Nru a/include/asm-arm/proc-armv/system.h b/include/asm-arm/proc-armv/system.h
--- a/include/asm-arm/proc-armv/system.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-arm/proc-armv/system.h	Thu Aug  1 14:17:36 2002
@@ -43,17 +43,23 @@
 #endif
 
 /*
- * A couple of speedups for the ARM
+ * Save the current interrupt enable state.
  */
+#define local_save_flags(x)					\
+	({							\
+	__asm__ __volatile__(					\
+	"mrs	%0, cpsr		@ local_save_flags"	\
+	: "=r" (x) : : "memory");				\
+	})
 
 /*
  * Save the current interrupt enable state & disable IRQs
  */
-#define local_save_flags_cli(x)					\
+#define local_irq_save(x)					\
 	({							\
 		unsigned long temp;				\
 	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ save_flags_cli\n"	\
+	"mrs	%0, cpsr		@ local_irq_save\n"	\
 "	orr	%1, %0, #128\n"					\
 "	msr	cpsr_c, %1"					\
 	: "=r" (x), "=r" (temp)					\
@@ -64,11 +70,11 @@
 /*
  * Enable IRQs
  */
-#define local_irq_enable()							\
+#define local_irq_enable()					\
 	({							\
 		unsigned long temp;				\
 	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ sti\n"		\
+	"mrs	%0, cpsr		@ local_irq_enable\n"	\
 "	bic	%0, %0, #128\n"					\
 "	msr	cpsr_c, %0"					\
 	: "=r" (temp)						\
@@ -79,11 +85,11 @@
 /*
  * Disable IRQs
  */
-#define local_irq_disable()							\
+#define local_irq_disable()					\
 	({							\
 		unsigned long temp;				\
 	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ cli\n"		\
+	"mrs	%0, cpsr		@ local_irq_disable\n"	\
 "	orr	%0, %0, #128\n"					\
 "	msr	cpsr_c, %0"					\
 	: "=r" (temp)						\
@@ -122,21 +128,11 @@
 	})
 
 /*
- * save current IRQ & FIQ state
- */
-#define local_save_flags(x)						\
-	__asm__ __volatile__(					\
-	"mrs	%0, cpsr		@ save_flags\n"		\
-	  : "=r" (x)						\
-	  :							\
-	  : "memory")
-
-/*
  * restore saved IRQ & FIQ state
  */
 #define local_irq_restore(x)					\
 	__asm__ __volatile__(					\
-	"msr	cpsr_c, %0		@ restore_flags\n"	\
+	"msr	cpsr_c, %0		@ local_irq_restore\n"	\
 	:							\
 	: "r" (x)						\
 	: "memory")
@@ -168,14 +164,14 @@
 	switch (size) {
 #ifdef swp_is_buggy
 		case 1:
-			local_save_flags_cli(flags);
+			local_irq_save(flags);
 			ret = *(volatile unsigned char *)ptr;
 			*(volatile unsigned char *)ptr = x;
 			local_irq_restore(flags);
 			break;
 
 		case 4:
-			local_save_flags_cli(flags);
+			local_irq_save(flags);
 			ret = *(volatile unsigned long *)ptr;
 			*(volatile unsigned long *)ptr = x;
 			local_irq_restore(flags);
diff -Nru a/include/asm-arm/processor.h b/include/asm-arm/processor.h
--- a/include/asm-arm/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/processor.h	Thu Aug  1 14:17:40 2002
@@ -59,7 +59,7 @@
 
 unsigned long get_wchan(struct task_struct *p);
 
-#define cpu_relax()			do { } while (0)
+#define cpu_relax()			barrier()
 
 /*
  * Create a new kernel thread
diff -Nru a/include/asm-arm/rmap.h b/include/asm-arm/rmap.h
--- a/include/asm-arm/rmap.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-arm/rmap.h	Thu Aug  1 14:17:36 2002
@@ -1,6 +1,6 @@
 #ifndef _ARM_RMAP_H
 #define _ARM_RMAP_H
 
-#include <asm/proc/rmap.h>
+#include <asm-generic/rmap.h>
 
 #endif /* _ARM_RMAP_H */
diff -Nru a/include/asm-arm/socket.h b/include/asm-arm/socket.h
--- a/include/asm-arm/socket.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-arm/socket.h	Thu Aug  1 14:17:39 2002
@@ -3,7 +3,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-arm/softirq.h b/include/asm-arm/softirq.h
--- a/include/asm-arm/softirq.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-arm/softirq.h	Thu Aug  1 14:17:40 2002
@@ -1,26 +1,20 @@
 #ifndef __ASM_SOFTIRQ_H
 #define __ASM_SOFTIRQ_H
 
-#include <asm/atomic.h>
+#include <linux/preempt.h>
 #include <asm/hardirq.h>
 
-#define __cpu_bh_enable(cpu) \
-		do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0)
-#define cpu_bh_disable(cpu) \
-		do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0)
+#define local_bh_disable() \
+	do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0)
+#define __local_bh_enable() \
+	do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
 
-#define local_bh_disable()	cpu_bh_disable(smp_processor_id())
-#define __local_bh_enable()	__cpu_bh_enable(smp_processor_id())
-
-#define in_softirq()		(local_bh_count(smp_processor_id()) != 0)
-
-#define _local_bh_enable()						\
+#define local_bh_enable()						\
 do {									\
-	unsigned int *ptr = &local_bh_count(smp_processor_id());	\
-	if (!--*ptr && ptr[-2])						\
+	__local_bh_enable();						\
+	if (unlikely(!in_interrupt() && softirq_pending(smp_processor_id()))) \
 		__asm__("bl%? __do_softirq": : : "lr");/* out of line */\
+	preempt_check_resched();					\
 } while (0)
-
-#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0)
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-arm/system.h	Thu Aug  1 14:17:36 2002
@@ -64,20 +64,12 @@
 struct thread_info;
 extern struct task_struct *__switch_to(struct thread_info *, struct thread_info *);
 
-#define prepare_arch_schedule(prev)		do { } while(0)
-#define finish_arch_schedule(prev)		do { } while(0)
-#define prepare_arch_switch(rq)			do { } while(0)
-#define finish_arch_switch(rq)			spin_unlock_irq(&(rq)->lock)
-
 #define switch_to(prev,next,last)					\
 	do {			 					\
 		__switch_to(prev->thread_info,next->thread_info);	\
 		mb();							\
 	} while (0)
 
-/* For spinlocks etc */
-#define local_irq_save(x)	local_save_flags_cli(x)
-
 #ifdef CONFIG_SMP
 #error SMP not supported
 
@@ -91,12 +83,8 @@
 #define smp_rmb()		barrier()
 #define smp_wmb()		barrier()
 
-#define cli()			local_irq_disable()
-#define sti()			local_irq_enable()
 #define clf()			__clf()
 #define stf()			__stf()
-#define save_flags(x)		local_save_flags(x)
-#define restore_flags(x)	local_irq_restore(x)
 
 #endif /* CONFIG_SMP */
 
diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
--- a/include/asm-arm/unistd.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-arm/unistd.h	Thu Aug  1 14:17:41 2002
@@ -200,8 +200,8 @@
 #define __NR_rt_sigtimedwait		(__NR_SYSCALL_BASE+177)
 #define __NR_rt_sigqueueinfo		(__NR_SYSCALL_BASE+178)
 #define __NR_rt_sigsuspend		(__NR_SYSCALL_BASE+179)
-#define __NR_pread			(__NR_SYSCALL_BASE+180)
-#define __NR_pwrite			(__NR_SYSCALL_BASE+181)
+#define __NR_pread64			(__NR_SYSCALL_BASE+180)
+#define __NR_pwrite64			(__NR_SYSCALL_BASE+181)
 #define __NR_chown			(__NR_SYSCALL_BASE+182)
 #define __NR_getcwd			(__NR_SYSCALL_BASE+183)
 #define __NR_capget			(__NR_SYSCALL_BASE+184)
diff -Nru a/include/asm-cris/processor.h b/include/asm-cris/processor.h
--- a/include/asm-cris/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-cris/processor.h	Thu Aug  1 14:17:40 2002
@@ -142,6 +142,6 @@
 #define init_task       (init_task_union.task)
 #define init_stack      (init_task_union.stack)
 
-#define cpu_relax()     do { } while (0)
+#define cpu_relax()     barrier()
 
 #endif /* __ASM_CRIS_PROCESSOR_H */
diff -Nru a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
--- a/include/asm-cris/unistd.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-cris/unistd.h	Thu Aug  1 14:17:40 2002
@@ -185,8 +185,8 @@
 #define __NR_rt_sigtimedwait	177
 #define __NR_rt_sigqueueinfo	178
 #define __NR_rt_sigsuspend	179
-#define __NR_pread		180
-#define __NR_pwrite		181
+#define __NR_pread64		180
+#define __NR_pwrite64		181
 #define __NR_chown		182
 #define __NR_getcwd		183
 #define __NR_capget		184
diff -Nru a/include/asm-i386/desc.h b/include/asm-i386/desc.h
--- a/include/asm-i386/desc.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-i386/desc.h	Thu Aug  1 14:17:36 2002
@@ -86,11 +86,9 @@
 	_set_tssldt_desc(&cpu_gdt_table[cpu][LDT_ENTRY], (int)addr, ((size << 3)-1), 0x82);
 }
 
-#define TLS_FLAGS_MASK			0x00000007
+#define TLS_FLAGS_MASK			0x00000001
 
-#define TLS_FLAG_LIMIT_IN_PAGES		0x00000001
-#define TLS_FLAG_WRITABLE		0x00000002
-#define TLS_FLAG_CLEAR			0x00000004
+#define TLS_FLAG_WRITABLE		0x00000001
 
 static inline void load_TLS_desc(struct thread_struct *t, unsigned int cpu)
 {
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-i386/processor.h	Thu Aug  1 14:17:36 2002
@@ -376,8 +376,7 @@
 	unsigned long		v86flags, v86mask, v86mode, saved_esp0;
 /* IO permissions */
 	unsigned long	*ts_io_bitmap;
-/* TLS info and cached descriptor */
-	unsigned int tls_base, tls_limit, tls_flags;
+/* TLS cached descriptor */
 	struct desc_struct tls_desc;
 };
 
@@ -456,7 +455,7 @@
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
 static inline void rep_nop(void)
 {
-	__asm__ __volatile__("rep;nop");
+	__asm__ __volatile__("rep;nop": : :"memory");
 }
 
 #define cpu_relax()	rep_nop()
diff -Nru a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h
--- a/include/asm-i386/rwsem.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-i386/rwsem.h	Thu Aug  1 14:17:40 2002
@@ -118,6 +118,29 @@
 }
 
 /*
+ * trylock for reading -- returns 1 if successful, 0 if contention
+ */
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+	__s32 result, tmp;
+	__asm__ __volatile__(
+		"# beginning __down_read_trylock\n\t"
+		"  movl      %0,%1\n\t"
+		"1:\n\t"
+		"  movl	     %1,%2\n\t"
+		"  addl      %3,%2\n\t"
+		"  jle	     2f\n\t"
+LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
+		"  jnz	     1b\n\t"
+		"2:\n\t"
+		"# ending __down_read_trylock\n\t"
+		: "+m"(sem->count), "=&a"(result), "=&r"(tmp)
+		: "i"(RWSEM_ACTIVE_READ_BIAS)
+		: "memory", "cc");
+	return result>=0 ? 1 : 0;
+}
+
+/*
  * lock for writing
  */
 static inline void __down_write(struct rw_semaphore *sem)
@@ -142,6 +165,19 @@
 		: "=m"(sem->count), "=d"(tmp)
 		: "a"(sem), "1"(tmp), "m"(sem->count)
 		: "memory", "cc");
+}
+
+/*
+ * trylock for writing -- returns 1 if successful, 0 if contention
+ */
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+	signed long ret = cmpxchg(&sem->count,
+				  RWSEM_UNLOCKED_VALUE, 
+				  RWSEM_ACTIVE_WRITE_BIAS);
+	if (ret == RWSEM_UNLOCKED_VALUE)
+		return 1;
+	return 0;
 }
 
 /*
diff -Nru a/include/asm-i386/smp.h b/include/asm-i386/smp.h
--- a/include/asm-i386/smp.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-i386/smp.h	Thu Aug  1 14:17:36 2002
@@ -85,7 +85,9 @@
  */
 #define smp_processor_id() (current_thread_info()->cpu)
 
-#define cpu_possible(cpu) (phys_cpu_present_map & (1<<(cpu)))
+extern volatile unsigned long cpu_callout_map;
+
+#define cpu_possible(cpu) (cpu_callout_map & (1<<(cpu)))
 #define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
 
 extern inline unsigned int num_online_cpus(void)
@@ -113,7 +115,6 @@
 	return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR));
 }
 
-extern volatile unsigned long cpu_callout_map;
 /* We don't mark CPUs online until __cpu_up(), so we need another measure */
 static inline int num_booting_cpus(void)
 {
diff -Nru a/include/asm-i386/socket.h b/include/asm-i386/socket.h
--- a/include/asm-i386/socket.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-i386/socket.h	Thu Aug  1 14:17:36 2002
@@ -3,7 +3,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h
--- a/include/asm-i386/spinlock.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-i386/spinlock.h	Thu Aug  1 14:17:39 2002
@@ -39,7 +39,7 @@
  * We make no fairness assumptions. They have a cost.
  */
 
-#define spin_is_locked(x)	(*(volatile char *)(&(x)->lock) <= 0)
+#define spin_is_locked(x)	(*(volatile signed char *)(&(x)->lock) <= 0)
 #define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
 
 #define spin_lock_string \
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-i386/unistd.h	Thu Aug  1 14:17:41 2002
@@ -184,8 +184,8 @@
 #define __NR_rt_sigtimedwait	177
 #define __NR_rt_sigqueueinfo	178
 #define __NR_rt_sigsuspend	179
-#define __NR_pread		180
-#define __NR_pwrite		181
+#define __NR_pread64		180
+#define __NR_pwrite64		181
 #define __NR_chown		182
 #define __NR_getcwd		183
 #define __NR_capget		184
@@ -247,6 +247,7 @@
 #define __NR_futex		240
 #define __NR_sched_setaffinity	241
 #define __NR_sched_getaffinity	242
+#define __NR_set_thread_area	243
 
 /* user-visible error numbers are in the range -1 - -124: see <asm-i386/errno.h> */
 
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-ia64/processor.h	Thu Aug  1 14:17:40 2002
@@ -616,7 +616,7 @@
 	asm volatile ("mov cr.lrr0=%0;; srlz.d" :: "r"(val) : "memory");
 }
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 
 static inline void
diff -Nru a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h
--- a/include/asm-ia64/socket.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ia64/socket.h	Thu Aug  1 14:17:36 2002
@@ -10,7 +10,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ia64/unistd.h	Thu Aug  1 14:17:36 2002
@@ -137,8 +137,8 @@
 #define __NR_flock			1145
 #define __NR_readv			1146
 #define __NR_writev			1147
-#define __NR_pread			1148
-#define __NR_pwrite			1149
+#define __NR_pread64			1148
+#define __NR_pwrite64			1149
 #define __NR__sysctl			1150
 #define __NR_mmap			1151
 #define __NR_munmap			1152
diff -Nru a/include/asm-m68k/processor.h b/include/asm-m68k/processor.h
--- a/include/asm-m68k/processor.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-m68k/processor.h	Thu Aug  1 14:17:41 2002
@@ -137,6 +137,6 @@
 	eip; })
 #define	KSTK_ESP(tsk)	((tsk) == current ? rdusp() : (tsk)->thread.usp)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 #endif
diff -Nru a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h
--- a/include/asm-m68k/socket.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-m68k/socket.h	Thu Aug  1 14:17:39 2002
@@ -3,7 +3,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
--- a/include/asm-m68k/unistd.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-m68k/unistd.h	Thu Aug  1 14:17:40 2002
@@ -184,8 +184,8 @@
 #define __NR_rt_sigtimedwait	177
 #define __NR_rt_sigqueueinfo	178
 #define __NR_rt_sigsuspend	179
-#define __NR_pread		180
-#define __NR_pwrite		181
+#define __NR_pread64		180
+#define __NR_pwrite64		181
 #define __NR_lchown		182
 #define __NR_getcwd		183
 #define __NR_capget		184
diff -Nru a/include/asm-mips/processor.h b/include/asm-mips/processor.h
--- a/include/asm-mips/processor.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-mips/processor.h	Thu Aug  1 14:17:36 2002
@@ -259,7 +259,7 @@
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-mips/socket.h b/include/asm-mips/socket.h
--- a/include/asm-mips/socket.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-mips/socket.h	Thu Aug  1 14:17:41 2002
@@ -4,7 +4,7 @@
 #include <asm/sockios.h>
 
 /*
- * For setsockoptions(2)
+ * For setsockopt(2)
  *
  * This defines are ABI conformant as far as Linux supports these ...
  */
diff -Nru a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
--- a/include/asm-mips/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-mips/unistd.h	Thu Aug  1 14:17:36 2002
@@ -212,8 +212,8 @@
 #define __NR_rt_sigtimedwait		(__NR_Linux + 197)
 #define __NR_rt_sigqueueinfo		(__NR_Linux + 198)
 #define __NR_rt_sigsuspend		(__NR_Linux + 199)
-#define __NR_pread			(__NR_Linux + 200)
-#define __NR_pwrite			(__NR_Linux + 201)
+#define __NR_pread64			(__NR_Linux + 200)
+#define __NR_pwrite64			(__NR_Linux + 201)
 #define __NR_chown			(__NR_Linux + 202)
 #define __NR_getcwd			(__NR_Linux + 203)
 #define __NR_capget			(__NR_Linux + 204)
diff -Nru a/include/asm-mips64/processor.h b/include/asm-mips64/processor.h
--- a/include/asm-mips64/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-mips64/processor.h	Thu Aug  1 14:17:40 2002
@@ -290,7 +290,7 @@
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-mips64/socket.h b/include/asm-mips64/socket.h
--- a/include/asm-mips64/socket.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-mips64/socket.h	Thu Aug  1 14:17:36 2002
@@ -12,7 +12,7 @@
 #include <asm/sockios.h>
 
 /*
- * For setsockoptions(2)
+ * For setsockopt(2)
  *
  * This defines are ABI conformant as far as Linux supports these ...
  */
diff -Nru a/include/asm-mips64/unistd.h b/include/asm-mips64/unistd.h
--- a/include/asm-mips64/unistd.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-mips64/unistd.h	Thu Aug  1 14:17:39 2002
@@ -447,8 +447,8 @@
 #define __NR_rt_sigtimedwait		(__NR_Linux + 197)
 #define __NR_rt_sigqueueinfo		(__NR_Linux + 198)
 #define __NR_rt_sigsuspend		(__NR_Linux + 199)
-#define __NR_pread			(__NR_Linux + 200)
-#define __NR_pwrite			(__NR_Linux + 201)
+#define __NR_pread64			(__NR_Linux + 200)
+#define __NR_pwrite64			(__NR_Linux + 201)
 #define __NR_chown			(__NR_Linux + 202)
 #define __NR_getcwd			(__NR_Linux + 203)
 #define __NR_capget			(__NR_Linux + 204)
diff -Nru a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
--- a/include/asm-parisc/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-parisc/processor.h	Thu Aug  1 14:17:40 2002
@@ -333,7 +333,7 @@
 #define init_task (init_task_union.task) 
 #define init_stack (init_task_union.stack)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 
 #endif /* __ASM_PARISC_PROCESSOR_H */
diff -Nru a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
--- a/include/asm-parisc/socket.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-parisc/socket.h	Thu Aug  1 14:17:41 2002
@@ -3,7 +3,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	0xffff
 
 #define SO_DEBUG	0x0001
diff -Nru a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
--- a/include/asm-parisc/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-parisc/unistd.h	Thu Aug  1 14:17:36 2002
@@ -598,8 +598,8 @@
 #define __NR_getitimer          (__NR_Linux + 105)
 #define __NR_capget             (__NR_Linux + 106)
 #define __NR_capset             (__NR_Linux + 107)
-#define __NR_pread              (__NR_Linux + 108)
-#define __NR_pwrite             (__NR_Linux + 109)
+#define __NR_pread64            (__NR_Linux + 108)
+#define __NR_pwrite64           (__NR_Linux + 109)
 #define __NR_getcwd             (__NR_Linux + 110)
 #define __NR_vhangup            (__NR_Linux + 111)
 #define __NR_idle               (__NR_Linux + 112)
diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
--- a/include/asm-ppc/hardirq.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc/hardirq.h	Thu Aug  1 14:17:36 2002
@@ -15,8 +15,6 @@
  */
 typedef struct {
 	unsigned long __softirq_pending;	/* set_bit is used on this */
-	unsigned int __local_irq_count;
-	unsigned int __local_bh_count;
 	unsigned int __syscall_count;
 	struct task_struct * __ksoftirqd_task;
 	unsigned int __last_jiffy_stamp;
@@ -25,91 +23,87 @@
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
 #define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
+
 /*
- * Are we in an interrupt context? Either doing bottom half
- * or hardware interrupt processing?
+ * We put the hardirq and softirq counter into the preemption
+ * counter. The bitmask has the following meaning:
+ *
+ * - bits 0-7 are the preemption count (max preemption depth: 256)
+ * - bits 8-15 are the softirq count (max # of softirqs: 256)
+ * - bits 16-23 are the hardirq count (max # of hardirqs: 256)
+ *
+ * - ( bit 26 is the PREEMPT_ACTIVE flag. )
+ *
+ * PREEMPT_MASK: 0x000000ff
+ * HARDIRQ_MASK: 0x0000ff00
+ * SOFTIRQ_MASK: 0x00ff0000
  */
-#define in_interrupt() ({ int __cpu = smp_processor_id(); \
-	(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
-
-#define in_irq() (local_irq_count(smp_processor_id()) != 0)
 
-#ifndef CONFIG_SMP
+#define PREEMPT_BITS	8
+#define SOFTIRQ_BITS	8
+#define HARDIRQ_BITS	8
+
+#define PREEMPT_SHIFT	0
+#define SOFTIRQ_SHIFT	(PREEMPT_SHIFT + PREEMPT_BITS)
+#define HARDIRQ_SHIFT	(SOFTIRQ_SHIFT + SOFTIRQ_BITS)
+
+#define __MASK(x)	((1UL << (x))-1)
+
+#define PREEMPT_MASK	(__MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
+#define HARDIRQ_MASK	(__MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
+#define SOFTIRQ_MASK	(__MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+
+#define hardirq_count()	(preempt_count() & HARDIRQ_MASK)
+#define softirq_count()	(preempt_count() & SOFTIRQ_MASK)
+#define irq_count()	(preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
+
+#define PREEMPT_OFFSET	(1UL << PREEMPT_SHIFT)
+#define SOFTIRQ_OFFSET	(1UL << SOFTIRQ_SHIFT)
+#define HARDIRQ_OFFSET	(1UL << HARDIRQ_SHIFT)
 
-#define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
-#define hardirq_endlock(cpu)	do { } while (0)
+/*
+ * The hardirq mask has to be large enough to have
+ * space for potentially all IRQ sources in the system
+ * nesting on a single CPU:
+ */
+#if (1 << HARDIRQ_BITS) < NR_IRQS
+# error HARDIRQ_BITS is too low!
+#endif
 
-#define hardirq_enter(cpu)	do { preempt_disable(); local_irq_count(cpu)++; } while (0)
-#define hardirq_exit(cpu)	do { local_irq_count(cpu)--; preempt_enable(); } while (0)
+/*
+ * Are we doing bottom half or hardware interrupt processing?
+ * Are we in a softirq context? Interrupt context?
+ */
+#define in_irq()		(hardirq_count())
+#define in_softirq()		(softirq_count())
+#define in_interrupt()		(irq_count())
 
-#define synchronize_irq()	do { } while (0)
-#define release_irqlock(cpu)    do { } while (0)
 
-#else /* CONFIG_SMP */
-
-#include <asm/atomic.h>
-
-extern unsigned char global_irq_holder;
-extern unsigned volatile long global_irq_lock;
-
-static inline int irqs_running (void)
-{
-	int i;
-
-	for (i = 0; i < NR_CPUS; i++)
-		if (local_irq_count(i))
-			return 1;
-	return 0;
-}
-
-static inline void release_irqlock(int cpu)
-{
-	/* if we didn't own the irq lock, just ignore.. */
-	if (global_irq_holder == (unsigned char) cpu) {
-		global_irq_holder = NO_PROC_ID;
-		clear_bit(0,&global_irq_lock);
-	}
-}
-
-static inline void hardirq_enter(int cpu)
-{
-	unsigned int loops = 10000000;
-
-	preempt_disable();
-	++local_irq_count(cpu);
-	while (test_bit(0,&global_irq_lock)) {
-		if (cpu == global_irq_holder) {
-			printk("uh oh, interrupt while we hold global irq lock! (CPU %d)\n", cpu);
-#ifdef CONFIG_XMON
-			xmon(0);
-#endif
-			break;
-		}
-		if (loops-- == 0) {
-			printk("do_IRQ waiting for irq lock (holder=%d)\n", global_irq_holder);
-#ifdef CONFIG_XMON
-			xmon(0);
-#endif
-		}
-	}
-}
-
-static inline void hardirq_exit(int cpu)
-{
-	--local_irq_count(cpu);
-	preempt_enable();
-}
-
-static inline int hardirq_trylock(int cpu)
-{
-	return !test_bit(0,&global_irq_lock);
-}
+#define hardirq_trylock()	(!in_interrupt())
+#define hardirq_endlock()	do { } while (0)
 
-#define hardirq_endlock(cpu)	do { } while (0)
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
 
-extern void synchronize_irq(void);
+#if CONFIG_PREEMPT
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
+#else
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
+#define irq_exit()							\
+do {									\
+	preempt_count() -= IRQ_EXIT_OFFSET;				\
+	if (!in_interrupt() && softirq_pending(smp_processor_id()))	\
+		do_softirq();						\
+	preempt_enable_no_resched();					\
+} while (0)
 
+#ifndef CONFIG_SMP
+# define synchronize_irq(irq)	barrier()
+#else
+  extern void synchronize_irq(unsigned int irq);
 #endif /* CONFIG_SMP */
+
+extern void show_stack(unsigned long *sp);
 
 #endif /* __ASM_HARDIRQ_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/hw_irq.h b/include/asm-ppc/hw_irq.h
--- a/include/asm-ppc/hw_irq.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-ppc/hw_irq.h	Thu Aug  1 14:17:41 2002
@@ -8,21 +8,18 @@
 #ifndef _PPC_HW_IRQ_H
 #define _PPC_HW_IRQ_H
 
-extern unsigned long timer_interrupt_intercept;
-extern unsigned long do_IRQ_intercept;
-extern int timer_interrupt(struct pt_regs *);
+extern void timer_interrupt(struct pt_regs *);
 extern void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
 
 #define INLINE_IRQS
 
-#ifdef INLINE_IRQS
-
 #define mfmsr()		({unsigned int rval; \
 			asm volatile("mfmsr %0" : "=r" (rval)); rval;})
 #define mtmsr(v)	asm volatile("mtmsr %0" : : "r" (v))
 
-#define local_save_flags(flags)	((flags) = mfmsr())
-#define local_irq_restore(flags)	mtmsr(flags)
+#define irqs_disabled()	((mfmsr() & MSR_EE) == 0)
+
+#ifdef INLINE_IRQS
 
 static inline void local_irq_disable(void)
 {
@@ -40,7 +37,7 @@
 	mtmsr(msr | MSR_EE);
 }
 
-static inline void __do_save_and_cli(unsigned long *flags)
+static inline void local_irq_save_ptr(unsigned long *flags)
 {
 	unsigned long msr;
 	msr = mfmsr();
@@ -49,7 +46,9 @@
 	__asm__ __volatile__("": : :"memory");
 }
 
-#define local_irq_save(flags)          __do_save_and_cli(&flags)
+#define local_save_flags(flags)		((flags) = mfmsr())
+#define local_irq_save(flags)		local_irq_save_ptr(&flags)
+#define local_irq_restore(flags)	mtmsr(flags)
 
 #else
 
@@ -57,9 +56,8 @@
 extern void local_irq_disable(void);
 extern void local_irq_restore(unsigned long);
 extern void local_save_flags_ptr(unsigned long *);
-extern unsigned long local_irq_enable_end, local_irq_disable_end, local_irq_restore_end, local_save_flags_ptr_end;
 
-#define local_save_flags(flags) local_save_flags_ptr((unsigned long *)&flags)
+#define local_save_flags(flags) local_save_flags_ptr(&flags)
 #define local_irq_save(flags) ({local_save_flags(flags);local_irq_disable();})
 
 #endif
diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
--- a/include/asm-ppc/pgtable.h	Thu Aug  1 14:17:37 2002
+++ b/include/asm-ppc/pgtable.h	Thu Aug  1 14:17:37 2002
@@ -246,6 +246,23 @@
 #define _PAGE_KERNEL	_PAGE_BASE | _PAGE_WRENABLE | _PAGE_SHARED | _PAGE_HWEXEC
 #define _PAGE_IO	_PAGE_KERNEL | _PAGE_NO_CACHE | _PAGE_GUARDED
 
+#define _PAGE_RAM	_PAGE_KERNEL
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
+/* We want the debuggers to be able to set breakpoints anywhere, so
+ * don't write protect the kernel text */
+#define _PAGE_RAM_TEXT	_PAGE_RAM
+#else
+#ifdef CONFIG_PPC_STD_MMU
+/* On standard PPC MMU, no user access implies kernel read/write
+ * access, so to write-protect the kernel text we must turn on user
+ * access */
+#define _PAGE_RAM_TEXT	(_PAGE_RAM & ~_PAGE_WRENABLE) | _PAGE_USER
+#else
+#define _PAGE_RAM_TEXT	(_PAGE_RAM & ~_PAGE_WRENABLE)
+#endif
+#endif
+
 #define PAGE_NONE	__pgprot(_PAGE_BASE)
 #define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
 #define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
diff -Nru a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h
--- a/include/asm-ppc/processor.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc/processor.h	Thu Aug  1 14:17:36 2002
@@ -771,7 +771,7 @@
 
 #define have_of (_machine == _MACH_chrp || _machine == _MACH_Pmac)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 /*
  * Prefetch macros.
diff -Nru a/include/asm-ppc/rwsem.h b/include/asm-ppc/rwsem.h
--- a/include/asm-ppc/rwsem.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-ppc/rwsem.h	Thu Aug  1 14:17:41 2002
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.rwsem.h 1.6 05/17/01 18:14:25 cort
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff
@@ -55,6 +55,7 @@
 extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
 extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
 static inline void init_rwsem(struct rw_semaphore *sem)
 {
@@ -122,6 +123,19 @@
 static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
 {
 	atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+	if (tmp < 0)
+		rwsem_downgrade_wake(sem);
 }
 
 /*
diff -Nru a/include/asm-ppc/smplock.h b/include/asm-ppc/smplock.h
--- a/include/asm-ppc/smplock.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-ppc/smplock.h	Thu Aug  1 14:17:39 2002
@@ -18,7 +18,7 @@
 #ifdef CONFIG_SMP
 #define kernel_locked()		spin_is_locked(&kernel_flag)
 #elif defined(CONFIG_PREEMPT)
-#define kernel_locked()		preempt_get_count()
+#define kernel_locked()		preempt_count()
 #endif
 
 /*
diff -Nru a/include/asm-ppc/socket.h b/include/asm-ppc/socket.h
--- a/include/asm-ppc/socket.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-ppc/socket.h	Thu Aug  1 14:17:40 2002
@@ -12,7 +12,7 @@
 #define SIOCATMARK	0x8905
 #define SIOCGSTAMP	0x8906		/* Get stamp */
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-ppc/softirq.h b/include/asm-ppc/softirq.h
--- a/include/asm-ppc/softirq.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-ppc/softirq.h	Thu Aug  1 14:17:41 2002
@@ -5,34 +5,30 @@
 #ifndef __ASM_SOFTIRQ_H
 #define __ASM_SOFTIRQ_H
 
-#include <asm/atomic.h>
+#include <linux/preempt.h>
 #include <asm/hardirq.h>
 
 #define local_bh_disable()			\
 do {						\
-	preempt_disable();			\
-	local_bh_count(smp_processor_id())++;	\
+	preempt_count() += SOFTIRQ_OFFSET;	\
 	barrier();				\
 } while (0)
 
 #define __local_bh_enable()			\
 do {						\
 	barrier();				\
-	local_bh_count(smp_processor_id())--;	\
-	preempt_enable();			\
+	preempt_count() -= SOFTIRQ_OFFSET;	\
 } while (0)
 
-#define local_bh_enable()				\
-do {							\
-	barrier();					\
-	if (!--local_bh_count(smp_processor_id())	\
-	    && softirq_pending(smp_processor_id())) {	\
-		do_softirq();				\
-	}						\
-	preempt_enable();				\
+#define local_bh_enable()					\
+do {								\
+	__local_bh_enable();					\
+	if (unlikely(!in_interrupt()				\
+		     && softirq_pending(smp_processor_id())))	\
+		do_softirq();					\
+	if (preempt_count() == 0)				\
+		preempt_check_resched(); 			\
 } while (0)
-
-#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
 
 #endif	/* __ASM_SOFTIRQ_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/system.h b/include/asm-ppc/system.h
--- a/include/asm-ppc/system.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-ppc/system.h	Thu Aug  1 14:17:40 2002
@@ -96,27 +96,6 @@
 struct pt_regs;
 extern void dump_regs(struct pt_regs *);
 
-#ifndef CONFIG_SMP
-
-#define cli()	local_irq_disable()
-#define sti()	local_irq_enable()
-#define save_flags(flags)	local_save_flags(flags)
-#define restore_flags(flags)	local_irq_restore(flags)
-#define save_and_cli(flags)	local_irq_save(flags)
-
-#else /* CONFIG_SMP */
-
-extern void __global_cli(void);
-extern void __global_sti(void);
-extern unsigned long __global_save_flags(void);
-extern void __global_restore_flags(unsigned long);
-#define cli() __global_cli()
-#define sti() __global_sti()
-#define save_flags(x) ((x)=__global_save_flags())
-#define restore_flags(x) __global_restore_flags(x)
-
-#endif /* !CONFIG_SMP */
-
 static __inline__ unsigned long
 xchg_u32(volatile void *p, unsigned long val)
 {
diff -Nru a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
--- a/include/asm-ppc/thread_info.h	Thu Aug  1 14:17:37 2002
+++ b/include/asm-ppc/thread_info.h	Thu Aug  1 14:17:37 2002
@@ -22,24 +22,24 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	int			cpu;		/* cpu we're on */
-	int			preempt_count;	/* not used at present */
-	int			softirq_count;
-	int			hardirq_count;
+	int			preempt_count;
 };
 
-/*
- * macros/functions for gaining access to the thread information structure
- */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
-	task:		&tsk,			\
-	exec_domain:	&default_exec_domain,	\
-	flags:		0,			\
-	cpu:		0,			\
+	.task =		&tsk,			\
+	.exec_domain =	&default_exec_domain,	\
+	.flags =	0,			\
+	.cpu =		0,			\
+	.preempt_count = 1			\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
 #define init_stack		(init_thread_union.stack)
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ */
 
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
diff -Nru a/include/asm-ppc/tlb.h b/include/asm-ppc/tlb.h
--- a/include/asm-ppc/tlb.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc/tlb.h	Thu Aug  1 14:17:36 2002
@@ -1,4 +1,61 @@
 /*
- * BK Id: SCCS/s.tlb.h 1.5 05/17/01 18:14:26 cort
+ *	TLB shootdown specifics for PPC
+ *
+ * Copyright (C) 2002 Paul Mackerras, IBM Corp.
+ *
+ * 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.
  */
+#ifndef _PPC_TLB_H
+#define _PPC_TLB_H
+
+#include <linux/config.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_PPC_STD_MMU
+/* Classic PPC with hash-table based MMU... */
+
+struct free_pte_ctx;
+extern void tlb_flush(struct free_pte_ctx *tlb);
+
+/* Get the generic bits... */
 #include <asm-generic/tlb.h>
+
+/* Nothing needed here in fact... */
+#define tlb_start_vma(tlb, vma)	do { } while (0)
+#define tlb_end_vma(tlb, vma)	do { } while (0)
+
+extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep,
+			     unsigned long address);
+
+static inline void tlb_remove_tlb_entry(mmu_gather_t *tlb, pte_t *ptep,
+					unsigned long address)
+{
+	if (pte_val(*ptep) & _PAGE_HASHPTE)
+		flush_hash_entry(tlb->mm, ptep, address);
+}
+
+#else
+/* Embedded PPC with software-loaded TLB, very simple... */
+
+struct flush_tlb_arch { };
+
+#define tlb_init_arch(tlb, full_flush)	do { } while (0)
+#define tlb_finish_arch(tlb)		do { } while (0)
+#define tlb_start_vma(tlb, vma)		do { } while (0)
+#define tlb_end_vma(tlb, vma)		do { } while (0)
+#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_flush(tlb)			flush_tlb_mm((tlb)->mm)
+
+/* Get the generic bits... */
+#include <asm-generic/tlb.h>
+
+#endif /* CONFIG_PPC_STD_MMU */
+
+#endif /* __PPC_TLB_H */
diff -Nru a/include/asm-ppc/tlbflush.h b/include/asm-ppc/tlbflush.h
--- a/include/asm-ppc/tlbflush.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc/tlbflush.h	Thu Aug  1 14:17:36 2002
@@ -22,8 +22,6 @@
 
 #if defined(CONFIG_4xx)
 
-static inline void flush_tlb_all(void)
-	{ _tlbia(); }
 static inline void flush_tlb_mm(struct mm_struct *mm)
 	{ _tlbia(); }
 static inline void flush_tlb_page(struct vm_area_struct *vma,
@@ -40,8 +38,6 @@
 #elif defined(CONFIG_8xx)
 #define __tlbia()	asm volatile ("tlbia; sync" : : : "memory")
 
-static inline void flush_tlb_all(void)
-	{ __tlbia(); }
 static inline void flush_tlb_mm(struct mm_struct *mm)
 	{ __tlbia(); }
 static inline void flush_tlb_page(struct vm_area_struct *vma,
@@ -58,7 +54,6 @@
 #else	/* 6xx, 7xx, 7xxx cpus */
 struct mm_struct;
 struct vm_area_struct;
-extern void flush_tlb_all(void);
 extern void flush_tlb_mm(struct mm_struct *mm);
 extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
 extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc/unistd.h	Thu Aug  1 14:17:36 2002
@@ -186,8 +186,8 @@
 #define __NR_rt_sigtimedwait	176
 #define __NR_rt_sigqueueinfo	177
 #define __NR_rt_sigsuspend	178
-#define __NR_pread		179
-#define __NR_pwrite		180
+#define __NR_pread64		179
+#define __NR_pwrite64		180
 #define __NR_chown		181
 #define __NR_getcwd		182
 #define __NR_capget		183
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc64/processor.h	Thu Aug  1 14:17:36 2002
@@ -692,7 +692,7 @@
 #define KSTK_EIP(tsk)  ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
 #define KSTK_ESP(tsk)  ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0)
 
-#define cpu_relax()     do { } while (0)
+#define cpu_relax()     barrier()
 
 /*
  * Prefetch macros.
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-ppc64/unistd.h	Thu Aug  1 14:17:36 2002
@@ -188,8 +188,8 @@
 #define __NR_rt_sigtimedwait	176
 #define __NR_rt_sigqueueinfo	177
 #define __NR_rt_sigsuspend	178
-#define __NR_pread		179
-#define __NR_pwrite		180
+#define __NR_pread64		179
+#define __NR_pwrite64		180
 #define __NR_chown		181
 #define __NR_getcwd		182
 #define __NR_capget		183
diff -Nru a/include/asm-s390/processor.h b/include/asm-s390/processor.h
--- a/include/asm-s390/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-s390/processor.h	Thu Aug  1 14:17:40 2002
@@ -134,7 +134,7 @@
 #define KSTK_EIP(tsk)	(__KSTK_PTREGS(tsk)->psw.addr)
 #define KSTK_ESP(tsk)	(__KSTK_PTREGS(tsk)->gprs[15])
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 /*
  * Set of msr bits that gdb can change on behalf of a process.
diff -Nru a/include/asm-s390/socket.h b/include/asm-s390/socket.h
--- a/include/asm-s390/socket.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-s390/socket.h	Thu Aug  1 14:17:36 2002
@@ -11,7 +11,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
--- a/include/asm-s390/unistd.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-s390/unistd.h	Thu Aug  1 14:17:41 2002
@@ -170,8 +170,8 @@
 #define __NR_rt_sigtimedwait    177
 #define __NR_rt_sigqueueinfo    178
 #define __NR_rt_sigsuspend      179
-#define __NR_pread              180
-#define __NR_pwrite             181
+#define __NR_pread64            180
+#define __NR_pwrite64           181
 #define __NR_chown              182
 #define __NR_getcwd             183
 #define __NR_capget             184
diff -Nru a/include/asm-s390x/processor.h b/include/asm-s390x/processor.h
--- a/include/asm-s390x/processor.h	Thu Aug  1 14:17:39 2002
+++ b/include/asm-s390x/processor.h	Thu Aug  1 14:17:39 2002
@@ -151,7 +151,7 @@
 #define KSTK_EIP(tsk)	(__KSTK_PTREGS(tsk)->psw.addr)
 #define KSTK_ESP(tsk)	(__KSTK_PTREGS(tsk)->gprs[15])
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 /*
  * Set of msr bits that gdb can change on behalf of a process.
diff -Nru a/include/asm-s390x/unistd.h b/include/asm-s390x/unistd.h
--- a/include/asm-s390x/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-s390x/unistd.h	Thu Aug  1 14:17:36 2002
@@ -147,8 +147,8 @@
 #define __NR_rt_sigtimedwait    177
 #define __NR_rt_sigqueueinfo    178
 #define __NR_rt_sigsuspend      179
-#define __NR_pread              180
-#define __NR_pwrite             181
+#define __NR_pread64            180
+#define __NR_pwrite64           181
 #define __NR_getcwd             183
 #define __NR_capget             184
 #define __NR_capset             185
diff -Nru a/include/asm-sh/processor.h b/include/asm-sh/processor.h
--- a/include/asm-sh/processor.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-sh/processor.h	Thu Aug  1 14:17:40 2002
@@ -222,6 +222,6 @@
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 #endif /* __ASM_SH_PROCESSOR_H */
diff -Nru a/include/asm-sh/socket.h b/include/asm-sh/socket.h
--- a/include/asm-sh/socket.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-sh/socket.h	Thu Aug  1 14:17:40 2002
@@ -3,7 +3,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	1
 
 #define SO_DEBUG	1
diff -Nru a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
--- a/include/asm-sh/unistd.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-sh/unistd.h	Thu Aug  1 14:17:41 2002
@@ -189,8 +189,8 @@
 #define __NR_rt_sigtimedwait	177
 #define __NR_rt_sigqueueinfo	178
 #define __NR_rt_sigsuspend	179
-#define __NR_pread		180
-#define __NR_pwrite		181
+#define __NR_pread64		180
+#define __NR_pwrite64		181
 #define __NR_chown		182
 #define __NR_getcwd		183
 #define __NR_capget		184
diff -Nru a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h
--- a/include/asm-sparc/processor.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-sparc/processor.h	Thu Aug  1 14:17:41 2002
@@ -201,7 +201,7 @@
 #define init_task	(init_task_union.task)
 #define init_stack	(init_task_union.stack)
 
-#define cpu_relax()	do { } while (0)
+#define cpu_relax()	barrier()
 
 #endif
 
diff -Nru a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
--- a/include/asm-sparc/socket.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-sparc/socket.h	Thu Aug  1 14:17:41 2002
@@ -4,7 +4,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	0xffff
 
 #define SO_DEBUG	0x0001
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-sparc/unistd.h	Thu Aug  1 14:17:36 2002
@@ -82,8 +82,8 @@
 #define __NR_getpagesize         64 /* Common                                      */
 #define __NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define __NR_vfork               66 /* Common                                      */
-#define __NR_pread               67 /* Linux Specific                              */
-#define __NR_pwrite              68 /* Linux Specific                              */
+#define __NR_pread64             67 /* Linux Specific                              */
+#define __NR_pwrite64            68 /* Linux Specific                              */
 #define __NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */
 #define __NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */
 #define __NR_mmap                71 /* Common                                      */
diff -Nru a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
--- a/include/asm-sparc64/processor.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-sparc64/processor.h	Thu Aug  1 14:17:36 2002
@@ -225,7 +225,7 @@
 #define KSTK_EIP(tsk)  ((tsk)->thread_info->kregs->tpc)
 #define KSTK_ESP(tsk)  ((tsk)->thread_info->kregs->u_regs[UREG_FP])
 
-#define cpu_relax()	udelay(1 + smp_processor_id())
+#define cpu_relax()	do { udelay(1 + smp_processor_id()); barrier(); } while  (0)
 
 #endif /* !(__ASSEMBLY__) */
 
diff -Nru a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
--- a/include/asm-sparc64/socket.h	Thu Aug  1 14:17:40 2002
+++ b/include/asm-sparc64/socket.h	Thu Aug  1 14:17:40 2002
@@ -4,7 +4,7 @@
 
 #include <asm/sockios.h>
 
-/* For setsockoptions(2) */
+/* For setsockopt(2) */
 #define SOL_SOCKET	0xffff
 
 #define SO_DEBUG	0x0001
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-sparc64/unistd.h	Thu Aug  1 14:17:36 2002
@@ -82,8 +82,8 @@
 #define __NR_getpagesize         64 /* Common                                      */
 #define __NR_msync               65 /* Common in newer 1.3.x revs...               */
 #define __NR_vfork               66 /* Common                                      */
-#define __NR_pread               67 /* Linux Specific                              */
-#define __NR_pwrite              68 /* Linux Specific                              */
+#define __NR_pread64             67 /* Linux Specific                              */
+#define __NR_pwrite64            68 /* Linux Specific                              */
 /* #define __NR_geteuid32        69    Linux sparc32, sbrk under SunOS             */
 /* #define __NR_getegid32        70    Linux sparc32, sstk under SunOS             */
 #define __NR_mmap                71 /* Common                                      */
diff -Nru a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
--- a/include/asm-x86_64/processor.h	Thu Aug  1 14:17:41 2002
+++ b/include/asm-x86_64/processor.h	Thu Aug  1 14:17:41 2002
@@ -367,7 +367,7 @@
 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */
 extern inline void rep_nop(void)
 {
-	__asm__ __volatile__("rep;nop");
+	__asm__ __volatile__("rep;nop": : :"memory");
 }
 
 #define cpu_has_fpu 1
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	Thu Aug  1 14:17:36 2002
+++ b/include/asm-x86_64/unistd.h	Thu Aug  1 14:17:36 2002
@@ -48,10 +48,10 @@
 
 #define __NR_ioctl                              16
 __SYSCALL(__NR_ioctl, sys_ioctl)
-#define __NR_pread                              17
-__SYSCALL(__NR_pread, sys_pread)
-#define __NR_pwrite                             18
-__SYSCALL(__NR_pwrite, sys_pwrite)
+#define __NR_pread64                            17
+__SYSCALL(__NR_pread64, sys_pread64)
+#define __NR_pwrite64                           18
+__SYSCALL(__NR_pwrite64, sys_pwrite64)
 #define __NR_readv                              19
 __SYSCALL(__NR_readv, sys_readv)
 #define __NR_writev                             20
diff -Nru a/include/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
--- a/include/linux/devfs_fs_kernel.h	Thu Aug  1 14:17:41 2002
+++ b/include/linux/devfs_fs_kernel.h	Thu Aug  1 14:17:41 2002
@@ -74,9 +74,9 @@
 extern devfs_handle_t devfs_get_handle (devfs_handle_t dir, const char *name,
 					unsigned int major,unsigned int minor,
 					char type, int traverse_symlinks);
-extern devfs_handle_t devfs_find_handle (devfs_handle_t dir, const char *name,
-					 unsigned int major,unsigned int minor,
-					 char type, int traverse_symlinks);
+extern void devfs_find_and_unregister (devfs_handle_t dir, const char *name,
+				       unsigned int major, unsigned int minor,
+				       char type, int traverse_symlinks);
 extern int devfs_get_flags (devfs_handle_t de, unsigned int *flags);
 extern int devfs_set_flags (devfs_handle_t de, unsigned int flags);
 extern int devfs_get_maj_min (devfs_handle_t de, 
@@ -94,12 +94,7 @@
 extern void devfs_auto_unregister (devfs_handle_t master,devfs_handle_t slave);
 extern devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master);
 extern const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen);
-extern int devfs_register_chrdev (unsigned int major, const char *name,
-				  struct file_operations *fops);
-extern int devfs_register_blkdev (unsigned int major, const char *name,
-				  struct block_device_operations *bdops);
-extern int devfs_unregister_chrdev (unsigned int major, const char *name);
-extern int devfs_unregister_blkdev (unsigned int major, const char *name);
+extern int devfs_only (void);
 
 extern void devfs_register_tape (devfs_handle_t de);
 extern void devfs_register_series (devfs_handle_t dir, const char *format,
@@ -164,14 +159,12 @@
 {
     return NULL;
 }
-static inline devfs_handle_t devfs_find_handle (devfs_handle_t dir,
-						const char *name,
-						unsigned int major,
-						unsigned int minor,
-						char type,
-						int traverse_symlinks)
+static inline void devfs_find_and_unregister (devfs_handle_t dir,
+					      const char *name,
+					      unsigned int major,
+					      unsigned int minor,
+					      char type, int traverse_symlinks)
 {
-    return NULL;
 }
 static inline int devfs_get_flags (devfs_handle_t de, unsigned int *flags)
 {
@@ -241,23 +234,9 @@
 {
     return NULL;
 }
-static inline int devfs_register_chrdev (unsigned int major, const char *name,
-					 struct file_operations *fops)
-{
-    return register_chrdev (major, name, fops);
-}
-static inline int devfs_register_blkdev (unsigned int major, const char *name,
-					 struct block_device_operations *bdops)
-{
-    return register_blkdev (major, name, bdops);
-}
-static inline int devfs_unregister_chrdev (unsigned int major,const char *name)
-{
-    return unregister_chrdev (major, name);
-}
-static inline int devfs_unregister_blkdev (unsigned int major,const char *name)
+static inline int devfs_only (void)
 {
-    return unregister_blkdev (major, name);
+    return 0;
 }
 
 static inline void devfs_register_tape (devfs_handle_t de)
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/device.h	Thu Aug  1 14:17:40 2002
@@ -160,8 +160,6 @@
 	void	(*release)(struct device * dev);
 };
 
-#define to_device(d) container_of(d, struct device, dir)
-
 static inline struct device *
 list_to_dev(struct list_head *node)
 {
@@ -179,8 +177,24 @@
  */
 extern int device_register(struct device * dev);
 
-extern int device_create_file(struct device *device, struct driver_file_entry * entry);
-extern void device_remove_file(struct device * dev, const char * name);
+
+/* driverfs interface for exporting device attributes */
+
+struct device_attribute {
+	struct attribute	attr;
+	ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
+	ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+};
+
+#define DEVICE_ATTR(_name,_str,_mode,_show,_store)	\
+struct device_attribute dev_attr_##_name = { 		\
+	.attr = {.name	= _str,	.mode	= _mode },	\
+	.show	= _show,				\
+	.store	= _store,				\
+};
+
+extern int device_create_file(struct device *device, struct device_attribute * entry);
+extern void device_remove_file(struct device * dev, struct device_attribute * attr);
 
 /*
  * Platform "fixup" functions - allow the platform to have their say
diff -Nru a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
--- a/include/linux/dqblk_xfs.h	Thu Aug  1 14:17:41 2002
+++ b/include/linux/dqblk_xfs.h	Thu Aug  1 14:17:41 2002
@@ -30,8 +30,8 @@
  *
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
-#ifndef _LINUX_XQM_H
-#define _LINUX_XQM_H
+#ifndef _LINUX_DQBLK_XFS_H
+#define _LINUX_DQBLK_XFS_H
 
 #include <linux/types.h>
 
@@ -156,4 +156,4 @@
 	__u16		qs_iwarnlimit;	/* limit for num warnings */
 } fs_quota_stat_t;
 
-#endif	/* _LINUX_XQM_H */
+#endif	/* _LINUX_DQBLK_XFS_H */
diff -Nru a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h
--- a/include/linux/driverfs_fs.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/driverfs_fs.h	Thu Aug  1 14:17:36 2002
@@ -26,24 +26,26 @@
 #ifndef _DRIVER_FS_H_
 #define _DRIVER_FS_H_
 
+struct driver_dir_entry;
+struct attribute;
+
+struct driverfs_ops {
+	int	(*open)(struct driver_dir_entry *);
+	int	(*close)(struct driver_dir_entry *);
+	ssize_t	(*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
+	ssize_t	(*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
+};
+
 struct driver_dir_entry {
 	char			* name;
 	struct dentry		* dentry;
 	mode_t			mode;
-	struct list_head	files;
+	struct driverfs_ops	* ops;
 };
 
-struct device;
-
-struct driver_file_entry {
-	struct driver_dir_entry * parent;
-	struct list_head	node;
+struct attribute {
 	char			* name;
 	mode_t			mode;
-	struct dentry		* dentry;
-
-	ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
-	ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
 };
 
 extern int
@@ -53,13 +55,12 @@
 driverfs_remove_dir(struct driver_dir_entry * entry);
 
 extern int
-driverfs_create_file(struct driver_file_entry * entry,
+driverfs_create_file(struct attribute * attr,
 		     struct driver_dir_entry * parent);
 
 extern int 
 driverfs_create_symlink(struct driver_dir_entry * parent, 
-			struct driver_file_entry * entry,
-			char * target);
+			char * name, char * target);
 
 extern void
 driverfs_remove_file(struct driver_dir_entry *, const char * name);
diff -Nru a/include/linux/elevator.h b/include/linux/elevator.h
--- a/include/linux/elevator.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/elevator.h	Thu Aug  1 14:17:36 2002
@@ -6,13 +6,14 @@
 
 typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int);
 
-typedef void (elevator_merge_req_fn) (struct request *, struct request *);
+typedef void (elevator_merge_req_fn) (request_queue_t *, struct request *, struct request *);
 
 typedef struct request *(elevator_next_req_fn) (request_queue_t *);
 
 typedef void (elevator_add_req_fn) (request_queue_t *, struct request *, struct list_head *);
 typedef int (elevator_queue_empty_fn) (request_queue_t *);
 typedef void (elevator_remove_req_fn) (request_queue_t *, struct request *);
+typedef struct list_head *(elevator_get_sort_head_fn) (request_queue_t *, struct request *);
 
 typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
 typedef void (elevator_exit_fn) (request_queue_t *, elevator_t *);
@@ -28,6 +29,7 @@
 	elevator_remove_req_fn *elevator_remove_req_fn;
 
 	elevator_queue_empty_fn *elevator_queue_empty_fn;
+	elevator_get_sort_head_fn *elevator_get_sort_head_fn;
 
 	elevator_init_fn *elevator_init_fn;
 	elevator_exit_fn *elevator_exit_fn;
@@ -45,6 +47,8 @@
 extern void elv_merge_requests(request_queue_t *, struct request *,
 			       struct request *);
 extern void elv_remove_request(request_queue_t *, struct request *);
+extern int elv_queue_empty(request_queue_t *);
+extern inline struct list_head *elv_get_sort_head(request_queue_t *, struct request *);
 
 /*
  * noop I/O scheduler. always merges, always inserts new request at tail
@@ -72,6 +76,10 @@
 
 extern int elevator_init(request_queue_t *, elevator_t *, elevator_t);
 extern void elevator_exit(request_queue_t *, elevator_t *);
+extern inline int bio_rq_in_between(struct bio *, struct request *, struct list_head *);
+extern inline int elv_rq_merge_ok(struct request *, struct bio *);
+extern inline int elv_try_merge(struct request *, struct bio *);
+extern inline int elv_try_last_merge(request_queue_t *, struct request **, struct bio *);
 
 /*
  * Return values from elevator merger
@@ -79,11 +87,5 @@
 #define ELEVATOR_NO_MERGE	0
 #define ELEVATOR_FRONT_MERGE	1
 #define ELEVATOR_BACK_MERGE	2
-
-/*
- * will change once we move to a more complex data structure than a simple
- * list for pending requests
- */
-#define elv_queue_empty(q)	list_empty(&(q)->queue_head)
 
 #endif
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Thu Aug  1 14:17:39 2002
+++ b/include/linux/fs.h	Thu Aug  1 14:17:39 2002
@@ -211,7 +211,11 @@
 extern void files_init(unsigned long);
 
 struct buffer_head;
-typedef int (get_block_t)(struct inode*,sector_t,struct buffer_head*,int);
+typedef int (get_block_t)(struct inode *inode, sector_t iblock,
+			struct buffer_head *bh_result, int create);
+typedef int (get_blocks_t)(struct inode *inode, sector_t iblock,
+			unsigned long max_blocks,
+			struct buffer_head *bh_result, int create);
 
 #include <linux/pipe_fs_i.h>
 /* #include <linux/umsdos_fs_i.h> */
@@ -757,6 +761,7 @@
 	int (*lock) (struct file *, int, struct file_lock *);
 	ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
 	ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
+	ssize_t (*sendfile) (struct file *, struct file *, loff_t *, size_t);
 	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
 	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 };
@@ -1234,11 +1239,12 @@
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
 extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *);
+extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t);
 extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t);
 ssize_t generic_file_direct_IO(int rw, struct inode *inode, char *buf,
 				loff_t offset, size_t count);
 int generic_direct_IO(int rw, struct inode *inode, char *buf,
-			loff_t offset, size_t count, get_block_t *get_block);
+			loff_t offset, size_t count, get_blocks_t *get_blocks);
 
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
diff -Nru a/include/linux/genhd.h b/include/linux/genhd.h
--- a/include/linux/genhd.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/genhd.h	Thu Aug  1 14:17:36 2002
@@ -70,12 +70,12 @@
 
 struct gendisk {
 	int major;			/* major number of driver */
+	int first_minor;
 	const char *major_name;		/* name of major driver */
 	int minor_shift;		/* number of times minor is shifted to
 					   get real minor */
 
 	struct hd_struct *part;		/* [indexed by minor] */
-	int *sizes;			/* [idem], device size in blocks */
 	int nr_real;			/* number of real devices */
 
 	struct gendisk *next;
diff -Nru a/include/linux/hdreg.h b/include/linux/hdreg.h
--- a/include/linux/hdreg.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/hdreg.h	Thu Aug  1 14:17:40 2002
@@ -2,279 +2,18 @@
 #define _LINUX_HDREG_H
 
 /*
- * This file contains some defines for the AT-hd-controller.
- * Various sources.
- */
-
-#define HD_IRQ 14			/* the standard disk interrupt */
-
-/* ide.c has its own port definitions in "ide.h" */
-
-/* Hd controller regs. Ref: IBM AT Bios-listing */
-#define HD_DATA		0x1f0		/* _CTL when writing */
-#define HD_ERROR	0x1f1		/* see err-bits */
-#define HD_NSECTOR	0x1f2		/* nr of sectors to read/write */
-#define HD_SECTOR	0x1f3		/* starting sector */
-#define HD_LCYL		0x1f4		/* starting cylinder */
-#define HD_HCYL		0x1f5		/* high byte of starting cyl */
-#define HD_CURRENT	0x1f6		/* 101dhhhh , d=drive, hhhh=head */
-#define HD_STATUS	0x1f7		/* see status-bits */
-#define HD_FEATURE	HD_ERROR	/* same io address, read=error, write=feature */
-#define HD_PRECOMP	HD_FEATURE	/* obsolete use of this port - predates IDE */
-#define HD_COMMAND	HD_STATUS	/* same io address, read=status, write=cmd */
-
-#define HD_CMD		0x3f6		/* used for resets */
-#define HD_ALTSTATUS	0x3f6		/* same as HD_STATUS but doesn't clear irq */
-
-/* remainder is shared between hd.c, ide.c, ide-cd.c, and the hdparm utility */
-
-/* Bits of HD_STATUS */
-#define ERR_STAT		0x01
-#define INDEX_STAT		0x02
-#define ECC_STAT		0x04	/* Corrected error */
-#define DRQ_STAT		0x08
-#define SEEK_STAT		0x10
-#define SERVICE_STAT		SEEK_STAT
-#define WRERR_STAT		0x20
-#define READY_STAT		0x40
-#define BUSY_STAT		0x80
-
-/* Bits for HD_ERROR */
-#define MARK_ERR		0x01	/* Bad address mark */
-#define TRK0_ERR		0x02	/* couldn't find track 0 */
-#define ABRT_ERR		0x04	/* Command aborted */
-#define MCR_ERR			0x08	/* media change request */
-#define ID_ERR			0x10	/* ID field not found */
-#define MC_ERR			0x20	/* media changed */
-#define ECC_ERR			0x40	/* Uncorrectable ECC error */
-#define BBD_ERR			0x80	/* pre-EIDE meaning:  block marked bad */
-#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
-
-/*
- * sector count bits
- */
-#define NSEC_CD			0x01
-#define NSEC_IO			0x02
-#define NSEC_REL		0x04
-
-/*
  * Command Header sizes for IOCTL commands
  */
-
 #define HDIO_DRIVE_CMD_HDR_SIZE		(4 * sizeof(u8))
 #define HDIO_DRIVE_HOB_HDR_SIZE		(8 * sizeof(u8))
 
-#define IDE_DRIVE_TASK_INVALID		-1
-#define IDE_DRIVE_TASK_NO_DATA		0
-#define IDE_DRIVE_TASK_SET_XFER		1
-
-#define IDE_DRIVE_TASK_IN		2
-
-#define IDE_DRIVE_TASK_OUT		3
-#define IDE_DRIVE_TASK_RAW_WRITE	4
-
-struct hd_drive_task_hdr {
-	u8 feature;
-	u8 sector_count;
-	u8 sector_number;
-	u8 low_cylinder;
-	u8 high_cylinder;
-	u8 device_head;
-} __attribute__((packed));
-
-/*
- * Define standard taskfile in/out register
- */
-#define IDE_TASKFILE_STD_OUT_FLAGS	0xFE
-#define IDE_TASKFILE_STD_IN_FLAGS	0xFE
-#define IDE_HOB_STD_OUT_FLAGS		0xC0
-#define IDE_HOB_STD_IN_FLAGS		0xC0
-
-#define TASKFILE_INVALID		0x7fff
-#define TASKFILE_48			0x8000
-
-#define TASKFILE_NO_DATA		0x0000
-
-#define TASKFILE_IN			0x0001
-#define TASKFILE_MULTI_IN		0x0002
-
-#define TASKFILE_OUT			0x0004
-#define TASKFILE_MULTI_OUT		0x0008
-#define TASKFILE_IN_OUT			0x0010
-
-#define TASKFILE_IN_DMA			0x0020
-#define TASKFILE_OUT_DMA		0x0040
-#define TASKFILE_IN_DMAQ		0x0080
-#define TASKFILE_OUT_DMAQ		0x0100
-
-#define TASKFILE_P_IN			0x0200
-#define TASKFILE_P_OUT			0x0400
-#define TASKFILE_P_IN_DMA		0x0800
-#define TASKFILE_P_OUT_DMA		0x1000
-#define TASKFILE_P_IN_DMAQ		0x2000
-#define TASKFILE_P_OUT_DMAQ		0x4000
-
-/* ATA/ATAPI Commands pre T13 Spec */
-#define WIN_NOP				0x00
-#define CFA_REQ_EXT_ERROR_CODE		0x03 /* CFA Request Extended Error Code */
-#define WIN_SRST			0x08 /* ATAPI soft reset command */
-#define WIN_DEVICE_RESET		0x08
-#define WIN_RESTORE			0x10
-#define WIN_READ			0x20 /* 28-Bit */
-#define WIN_READ_EXT			0x24 /* 48-Bit */
-#define WIN_READDMA_EXT			0x25 /* 48-Bit */
-#define WIN_READDMA_QUEUED_EXT		0x26 /* 48-Bit */
-#define WIN_READ_NATIVE_MAX_EXT		0x27 /* 48-Bit */
-#define WIN_MULTREAD_EXT		0x29 /* 48-Bit */
-#define WIN_WRITE			0x30 /* 28-Bit */
-#define WIN_WRITE_EXT			0x34 /* 48-Bit */
-#define WIN_WRITEDMA_EXT		0x35 /* 48-Bit */
-#define WIN_WRITEDMA_QUEUED_EXT		0x36 /* 48-Bit */
-#define WIN_SET_MAX_EXT			0x37 /* 48-Bit */
-#define CFA_WRITE_SECT_WO_ERASE		0x38 /* CFA Write Sectors without erase */
-#define WIN_MULTWRITE_EXT		0x39 /* 48-Bit */
-#define WIN_WRITE_VERIFY		0x3C /* 28-Bit */
-#define WIN_VERIFY			0x40 /* 28-Bit - Read Verify Sectors */
-#define WIN_VERIFY_EXT			0x42 /* 48-Bit */
-#define WIN_FORMAT			0x50
-#define WIN_INIT			0x60
-#define WIN_SEEK			0x70
-#define CFA_TRANSLATE_SECTOR		0x87 /* CFA Translate Sector */
-#define WIN_DIAGNOSE			0x90
-#define WIN_SPECIFY			0x91 /* set drive geometry translation */
-#define WIN_DOWNLOAD_MICROCODE		0x92
-#define WIN_STANDBYNOW2			0x94
-#define WIN_SETIDLE2			0x97
-#define WIN_CHECKPOWERMODE2		0x98
-#define WIN_SLEEPNOW2			0x99
-#define WIN_PACKETCMD			0xA0 /* Send a packet command. */
-#define WIN_PIDENTIFY			0xA1 /* identify ATAPI device	*/
-#define WIN_QUEUED_SERVICE		0xA2
-#define WIN_SMART			0xB0 /* self-monitoring and reporting */
-#define CFA_ERASE_SECTORS		0xC0
-#define WIN_MULTREAD			0xC4 /* read sectors using multiple mode*/
-#define WIN_MULTWRITE			0xC5 /* write sectors using multiple mode */
-#define WIN_SETMULT			0xC6 /* enable/disable multiple mode */
-#define WIN_READDMA_QUEUED		0xC7 /* read sectors using Queued DMA transfers */
-#define WIN_READDMA			0xC8 /* read sectors using DMA transfers */
-#define WIN_WRITEDMA			0xCA /* write sectors using DMA transfers */
-#define WIN_WRITEDMA_QUEUED		0xCC /* write sectors using Queued DMA transfers */
-#define CFA_WRITE_MULTI_WO_ERASE	0xCD /* CFA Write multiple without erase */
-#define WIN_GETMEDIASTATUS		0xDA
-#define WIN_DOORLOCK			0xDE /* lock door on removable drives */
-#define WIN_DOORUNLOCK			0xDF /* unlock door on removable drives */
-#define WIN_STANDBYNOW1			0xE0
-#define WIN_IDLEIMMEDIATE		0xE1 /* force drive to become "ready" */
-#define WIN_STANDBY			0xE2 /* Set device in Standby Mode */
-#define WIN_SETIDLE1			0xE3
-#define WIN_READ_BUFFER			0xE4 /* force read only 1 sector */
-#define WIN_CHECKPOWERMODE1		0xE5
-#define WIN_SLEEPNOW1			0xE6
-#define WIN_FLUSH_CACHE			0xE7
-#define WIN_WRITE_BUFFER		0xE8 /* force write only 1 sector */
-#define WIN_FLUSH_CACHE_EXT		0xEA /* 48-Bit */
-#define WIN_IDENTIFY			0xEC /* ask drive to identify itself	*/
-#define WIN_MEDIAEJECT			0xED
-#define WIN_IDENTIFY_DMA		0xEE /* same as WIN_IDENTIFY, but DMA */
-#define WIN_SETFEATURES			0xEF /* set special drive features */
-#define EXABYTE_ENABLE_NEST		0xF0
-#define WIN_SECURITY_SET_PASS		0xF1
-#define WIN_SECURITY_UNLOCK		0xF2
-#define WIN_SECURITY_ERASE_PREPARE	0xF3
-#define WIN_SECURITY_ERASE_UNIT		0xF4
-#define WIN_SECURITY_FREEZE_LOCK	0xF5
-#define WIN_SECURITY_DISABLE		0xF6
-#define WIN_READ_NATIVE_MAX		0xF8 /* return the native maximum address */
-#define WIN_SET_MAX			0xF9
-#define DISABLE_SEAGATE			0xFB
-
-/* WIN_SMART sub-commands */
-
-#define SMART_READ_VALUES		0xD0
-#define SMART_READ_THRESHOLDS		0xD1
-#define SMART_AUTOSAVE			0xD2
-#define SMART_SAVE			0xD3
-#define SMART_IMMEDIATE_OFFLINE		0xD4
-#define SMART_READ_LOG_SECTOR		0xD5
-#define SMART_WRITE_LOG_SECTOR		0xD6
-#define SMART_WRITE_THRESHOLDS		0xD7
-#define SMART_ENABLE			0xD8
-#define SMART_DISABLE			0xD9
-#define SMART_STATUS			0xDA
-#define SMART_AUTO_OFFLINE		0xDB
-
-/* Password used in TF4 & TF5 executing SMART commands */
-
-#define SMART_LCYL_PASS			0x4F
-#define SMART_HCYL_PASS			0xC2
-
-/* WIN_SETFEATURES sub-commands */
-
-#define SETFEATURES_EN_WCACHE	0x02	/* Enable write cache */
-#define SETFEATURES_XFER	0x03	/* Set transfer mode */
-#	define XFER_UDMA_7	0x47	/* 0100|0111 */
-#	define XFER_UDMA_6	0x46	/* 0100|0110 */
-#	define XFER_UDMA_5	0x45	/* 0100|0101 */
-#	define XFER_UDMA_4	0x44	/* 0100|0100 */
-#	define XFER_UDMA_3	0x43	/* 0100|0011 */
-#	define XFER_UDMA_2	0x42	/* 0100|0010 */
-#	define XFER_UDMA_1	0x41	/* 0100|0001 */
-#	define XFER_UDMA_0	0x40	/* 0100|0000 */
-#	define XFER_MW_DMA_2	0x22	/* 0010|0010 */
-#	define XFER_MW_DMA_1	0x21	/* 0010|0001 */
-#	define XFER_MW_DMA_0	0x20	/* 0010|0000 */
-#	define XFER_SW_DMA_2	0x12	/* 0001|0010 */
-#	define XFER_SW_DMA_1	0x11	/* 0001|0001 */
-#	define XFER_SW_DMA_0	0x10	/* 0001|0000 */
-#	define XFER_PIO_4	0x0C	/* 0000|1100 */
-#	define XFER_PIO_3	0x0B	/* 0000|1011 */
-#	define XFER_PIO_2	0x0A	/* 0000|1010 */
-#	define XFER_PIO_1	0x09	/* 0000|1001 */
-#	define XFER_PIO_0	0x08	/* 0000|1000 */
-#	define XFER_PIO_SLOW	0x00	/* 0000|0000 */
-#define SETFEATURES_DIS_DEFECT	0x04	/* Disable Defect Management */
-#define SETFEATURES_EN_APM	0x05	/* Enable advanced power management */
-#define SETFEATURES_DIS_MSN	0x31	/* Disable Media Status Notification */
-#define SETFEATURES_EN_AAM	0x42	/* Enable Automatic Acoustic Management */
-#define SETFEATURES_DIS_RLA	0x55	/* Disable read look-ahead feature */
-#define SETFEATURES_EN_RI	0x5D	/* Enable release interrupt */
-#define SETFEATURES_EN_SI	0x5E	/* Enable SERVICE interrupt */
-#define SETFEATURES_DIS_RPOD	0x66	/* Disable reverting to power on defaults */
-#define SETFEATURES_DIS_WCACHE	0x82	/* Disable write cache */
-#define SETFEATURES_EN_DEFECT	0x84	/* Enable Defect Management */
-#define SETFEATURES_DIS_APM	0x85	/* Disable advanced power management */
-#define SETFEATURES_EN_MSN	0x95	/* Enable Media Status Notification */
-#define SETFEATURES_EN_RLA	0xAA	/* Enable read look-ahead feature */
-#define SETFEATURES_PREFETCH	0xAB	/* Sets drive prefetch value */
-#define SETFEATURES_DIS_AAM	0xC2	/* Disable Automatic Acoustic Management */
-#define SETFEATURES_EN_RPOD	0xCC	/* Enable reverting to power on defaults */
-#define SETFEATURES_DIS_RI	0xDD	/* Disable release interrupt */
-#define SETFEATURES_DIS_SI	0xDE	/* Disable SERVICE interrupt */
-
-/* WIN_SECURITY sub-commands */
-
-#define SECURITY_SET_PASSWORD		0xBA
-#define SECURITY_UNLOCK			0xBB
-#define SECURITY_ERASE_PREPARE		0xBC
-#define SECURITY_ERASE_UNIT		0xBD
-#define SECURITY_FREEZE_LOCK		0xBE
-#define SECURITY_DISABLE_PASSWORD	0xBF
-
 struct hd_geometry {
-      u8 heads;
-      u8 sectors;
-      u16 cylinders;
+      __u8 heads;
+      __u8 sectors;
+      __u16 cylinders;
       unsigned long start;
 };
 
-/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */
-struct hd_big_geometry {
-	u8 heads;
-	u8 sectors;
-	u32 cylinders;
-	unsigned long start;
-};
-
 /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */
 #define HDIO_GETGEO		0x0301	/* get device geometry */
 #define HDIO_GET_UNMASKINTR	0x0302	/* get current unmask setting */
@@ -306,263 +45,8 @@
 #define HDIO_SET_QDMA		0x032e	/* change use-qdma flag */
 #define HDIO_SET_ADDRESS	0x032f	/* change lba addressing modes */
 
-/* bus states */
-enum {
-	BUSSTATE_OFF = 0,
-	BUSSTATE_ON,
-	BUSSTATE_TRISTATE
-};
-
 /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x033n/0x033n */
 /* 0x330 is reserved - used to be HDIO_GETGEO_BIG */
 #define HDIO_GETGEO_BIG_RAW	0x0331	/* */
-
-#define __NEW_HD_DRIVE_ID
-
-/*
- * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec.
- *
- * If you change something here, please remember to update fix_driveid() in
- * ide/probe.c.
- */
-struct hd_driveid {
-	u16	config;		/* lots of obsolete bit flags */
-	u16	cyls;		/* Obsolete, "physical" cyls */
-	u16	reserved2;	/* reserved (word 2) */
-	u16	heads;		/* Obsolete, "physical" heads */
-	u16	track_bytes;	/* unformatted bytes per track */
-	u16	sector_bytes;	/* unformatted bytes per sector */
-	u16	sectors;	/* Obsolete, "physical" sectors per track */
-	u16	vendor0;	/* vendor unique */
-	u16	vendor1;	/* vendor unique */
-	u16	vendor2;	/* Retired vendor unique */
-	u8	serial_no[20];	/* 0 = not_specified */
-	u16	buf_type;	/* Retired */
-	u16	buf_size;	/* Retired, 512 byte increments
-				 * 0 = not_specified
-				 */
-	u16	ecc_bytes;	/* for r/w long cmds; 0 = not_specified */
-	u8	fw_rev[8];	/* 0 = not_specified */
-	char	model[40];	/* 0 = not_specified */
-	u8	max_multsect;	/* 0=not_implemented */
-	u8	vendor3;	/* vendor unique */
-	u16	dword_io;	/* 0=not_implemented; 1=implemented */
-	u8	vendor4;	/* vendor unique */
-	u8	capability;	/* (upper byte of word 49)
-				 *  3:	IORDYsup
-				 *  2:	IORDYsw
-				 *  1:	LBA
-				 *  0:	DMA
-				 */
-	u16	reserved50;	/* reserved (word 50) */
-	u8	vendor5;	/* Obsolete, vendor unique */
-	u8	tPIO;		/* Obsolete, 0=slow, 1=medium, 2=fast */
-	u8	vendor6;	/* Obsolete, vendor unique */
-	u8	tDMA;		/* Obsolete, 0=slow, 1=medium, 2=fast */
-	u16	field_valid;	/* (word 53)
-				 *  2:	ultra_ok	word  88
-				 *  1:	eide_ok		words 64-70
-				 *  0:	cur_ok		words 54-58
-				 */
-	u16	cur_cyls;	/* Obsolete, logical cylinders */
-	u16	cur_heads;	/* Obsolete, l heads */
-	u16	cur_sectors;	/* Obsolete, l sectors per track */
-	u16	cur_capacity0;	/* Obsolete, l total sectors on drive */
-	u16	cur_capacity1;	/* Obsolete, (2 words, misaligned int)     */
-	u8	multsect;	/* current multiple sector count */
-	u8	multsect_valid;	/* when (bit0==1) multsect is ok */
-	u32	lba_capacity;	/* Obsolete, total number of sectors */
-	u16	dma_1word;	/* Obsolete, single-word dma info */
-	u16	dma_mword;	/* multiple-word dma info */
-	u16	eide_pio_modes; /* bits 0:mode3 1:mode4 */
-	u16	eide_dma_min;	/* min mword dma cycle time (ns) */
-	u16	eide_dma_time;	/* recommended mword dma cycle time (ns) */
-	u16	eide_pio;       /* min cycle time (ns), no IORDY  */
-	u16	eide_pio_iordy; /* min cycle time (ns), with IORDY */
-	u16	words69_70[2];	/* reserved words 69-70
-				 * future command overlap and queuing
-				 */
-	/* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
-	u16	words71_74[4];	/* reserved words 71-74
-				 * for IDENTIFY PACKET DEVICE command
-				 */
-	u16	queue_depth;	/* (word 75)
-				 * 15:5	reserved
-				 *  4:0	Maximum queue depth -1
-				 */
-	u16	words76_79[4];	/* reserved words 76-79 */
-	u16	major_rev_num;	/* (word 80) */
-	u16	minor_rev_num;	/* (word 81) */
-	u16	command_set_1;	/* (word 82) supported
-				 * 15:	Obsolete
-				 * 14:	NOP command
-				 * 13:	READ_BUFFER
-				 * 12:	WRITE_BUFFER
-				 * 11:	Obsolete
-				 * 10:	Host Protected Area
-				 *  9:	DEVICE Reset
-				 *  8:	SERVICE Interrupt
-				 *  7:	Release Interrupt
-				 *  6:	look-ahead
-				 *  5:	write cache
-				 *  4:	PACKET Command
-				 *  3:	Power Management Feature Set
-				 *  2:	Removable Feature Set
-				 *  1:	Security Feature Set
-				 *  0:	SMART Feature Set
-				 */
-	u16	command_set_2;	/* (word 83)
-				 * 15:	Shall be ZERO
-				 * 14:	Shall be ONE
-				 * 13:	FLUSH CACHE EXT
-				 * 12:	FLUSH CACHE
-				 * 11:	Device Configuration Overlay
-				 * 10:	48-bit Address Feature Set
-				 *  9:	Automatic Acoustic Management
-				 *  8:	SET MAX security
-				 *  7:	reserved 1407DT PARTIES
-				 *  6:	SetF sub-command Power-Up
-				 *  5:	Power-Up in Standby Feature Set
-				 *  4:	Removable Media Notification
-				 *  3:	APM Feature Set
-				 *  2:	CFA Feature Set
-				 *  1:	READ/WRITE DMA QUEUED
-				 *  0:	Download MicroCode
-				 */
-	u16	cfsse;		/* (word 84)
-				 * cmd set-feature supported extensions
-				 * 15:	Shall be ZERO
-				 * 14:	Shall be ONE
-				 * 13:3	reserved
-				 *  2:	Media Serial Number Valid
-				 *  1:	SMART selt-test supported
-				 *  0:	SMART error logging
-				 */
-	u16	cfs_enable_1;	/* (word 85)
-				 * command set-feature enabled
-				 * 15:	Obsolete
-				 * 14:	NOP command
-				 * 13:	READ_BUFFER
-				 * 12:	WRITE_BUFFER
-				 * 11:	Obsolete
-				 * 10:	Host Protected Area
-				 *  9:	DEVICE Reset
-				 *  8:	SERVICE Interrupt
-				 *  7:	Release Interrupt
-				 *  6:	look-ahead
-				 *  5:	write cache
-				 *  4:	PACKET Command
-				 *  3:	Power Management Feature Set
-				 *  2:	Removable Feature Set
-				 *  1:	Security Feature Set
-				 *  0:	SMART Feature Set
-				 */
-	u16	cfs_enable_2;	/* (word 86)
-				 * command set-feature enabled
-				 * 15:	Shall be ZERO
-				 * 14:	Shall be ONE
-				 * 13:	FLUSH CACHE EXT
-				 * 12:	FLUSH CACHE
-				 * 11:	Device Configuration Overlay
-				 * 10:	48-bit Address Feature Set
-				 *  9:	Automatic Acoustic Management
-				 *  8:	SET MAX security
-				 *  7:	reserved 1407DT PARTIES
-				 *  6:	SetF sub-command Power-Up
-				 *  5:	Power-Up in Standby Feature Set
-				 *  4:	Removable Media Notification
-				 *  3:	APM Feature Set
-				 *  2:	CFA Feature Set
-				 *  1:	READ/WRITE DMA QUEUED
-				 *  0:	Download MicroCode
-				 */
-	u16	csf_default;	/* (word 87)
-				 * command set-feature default
-				 * 15:	Shall be ZERO
-				 * 14:	Shall be ONE
-				 * 13:3	reserved
-				 *  2:	Media Serial Number Valid
-				 *  1:	SMART selt-test supported
-				 *  0:	SMART error logging
-				 */
-	u16	dma_ultra;	/* (word 88) */
-	u16	word89;		/* reserved (word 89) */
-	u16	word90;		/* reserved (word 90) */
-	u16	CurAPMvalues;	/* current APM values */
-	u16	word92;		/* reserved (word 92) */
-	u16	hw_config;	/* hardware config (word 93)
-				 * 15:
-				 * 14:
-				 * 13:
-				 * 12:
-				 * 11:
-				 * 10:
-				 *  9:
-				 *  8:
-				 *  7:
-				 *  6:
-				 *  5:
-				 *  4:
-				 *  3:
-				 *  2:
-				 *  1:
-				 *  0:
-				 */
-	u16	acoustic;	/* (word 94)
-				 * 15:8	Vendor's recommended value
-				 *  7:0	current value
-				 */
-	u16	words95_99[5];	/* reserved words 95-99 */
-	u64	lba_capacity_2;	/* 48-bit total number of sectors */
-	u16	words104_125[22];/* reserved words 104-125 */
-	u16	last_lun;	/* (word 126) */
-	u16	word127;	/* (word 127) Feature Set
-				 * Removable Media Notification
-				 * 15:2	reserved
-				 *  1:0	00 = not supported
-				 *	01 = supported
-				 *	10 = reserved
-				 *	11 = reserved
-				 */
-	u16	dlf;		/* (word 128)
-				 * device lock function
-				 * 15:9	reserved
-				 *  8	security level 1:max 0:high
-				 *  7:6	reserved
-				 *  5	enhanced erase
-				 *  4	expire
-				 *  3	frozen
-				 *  2	locked
-				 *  1	en/disabled
-				 *  0	capability
-				 */
-	u16	csfo;		/* (word 129)
-				 * current set features options
-				 * 15:4	reserved
-				 *  3:	auto reassign
-				 *  2:	reverting
-				 *  1:	read-look-ahead
-				 *  0:	write cache
-				 */
-	u16	words130_155[26];/* reserved vendor words 130-155 */
-	u16	word156;	/* reserved vendor word 156 */
-	u16	words157_159[3];/* reserved vendor words 157-159 */
-	u16	cfa_power;	/* (word 160) CFA Power Mode
-				 * 15 word 160 supported
-				 * 14 reserved
-				 * 13
-				 * 12
-				 * 11:0
-				 */
-	u16	words161_175[14];/* Reserved for CFA */
-	u16	words176_205[31];/* Current Media Serial Number */
-	u16	words206_254[48];/* reserved words 206-254 */
-	u16	integrity_word;	/* (word 255)
-				 * 15:8 Checksum
-				 *  7:0 Signature
-				 */
-} __attribute__((packed));
-
-#define IDE_NICE_DSC_OVERLAP	(0)	/* per the DSC overlap protocol */
 
 #endif
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/ide.h	Thu Aug  1 14:17:37 2002
@@ -8,7 +8,6 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/hdreg.h>
 #include <linux/hdsmart.h>
 #include <linux/blkdev.h>
 #include <linux/proc_fs.h>
@@ -51,7 +50,460 @@
  *  "No user-serviceable parts" beyond this point
  *****************************************************************************/
 
-typedef unsigned char	byte;	/* used everywhere */
+
+/* ATA/ATAPI Commands pre T13 Spec */
+#define WIN_NOP				0x00
+#define CFA_REQ_EXT_ERROR_CODE		0x03 /* CFA Request Extended Error Code */
+#define WIN_SRST			0x08 /* ATAPI soft reset command */
+#define WIN_DEVICE_RESET		0x08
+#define WIN_RESTORE			0x10
+#define WIN_READ			0x20 /* 28-Bit */
+#define WIN_READ_EXT			0x24 /* 48-Bit */
+#define WIN_READDMA_EXT			0x25 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT		0x26 /* 48-Bit */
+#define WIN_READ_NATIVE_MAX_EXT		0x27 /* 48-Bit */
+#define WIN_MULTREAD_EXT		0x29 /* 48-Bit */
+#define WIN_WRITE			0x30 /* 28-Bit */
+#define WIN_WRITE_EXT			0x34 /* 48-Bit */
+#define WIN_WRITEDMA_EXT		0x35 /* 48-Bit */
+#define WIN_WRITEDMA_QUEUED_EXT		0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT			0x37 /* 48-Bit */
+#define CFA_WRITE_SECT_WO_ERASE		0x38 /* CFA Write Sectors without erase */
+#define WIN_MULTWRITE_EXT		0x39 /* 48-Bit */
+#define WIN_WRITE_VERIFY		0x3C /* 28-Bit */
+#define WIN_VERIFY			0x40 /* 28-Bit - Read Verify Sectors */
+#define WIN_VERIFY_EXT			0x42 /* 48-Bit */
+#define WIN_FORMAT			0x50
+#define WIN_INIT			0x60
+#define WIN_SEEK			0x70
+#define CFA_TRANSLATE_SECTOR		0x87 /* CFA Translate Sector */
+#define WIN_DIAGNOSE			0x90
+#define WIN_SPECIFY			0x91 /* set drive geometry translation */
+#define WIN_DOWNLOAD_MICROCODE		0x92
+#define WIN_STANDBYNOW2			0x94
+#define WIN_SETIDLE2			0x97
+#define WIN_CHECKPOWERMODE2		0x98
+#define WIN_SLEEPNOW2			0x99
+#define WIN_PACKETCMD			0xA0 /* Send a packet command. */
+#define WIN_PIDENTIFY			0xA1 /* identify ATAPI device	*/
+#define WIN_QUEUED_SERVICE		0xA2
+#define WIN_SMART			0xB0 /* self-monitoring and reporting */
+#define CFA_ERASE_SECTORS		0xC0
+#define WIN_MULTREAD			0xC4 /* read sectors using multiple mode*/
+#define WIN_MULTWRITE			0xC5 /* write sectors using multiple mode */
+#define WIN_SETMULT			0xC6 /* enable/disable multiple mode */
+#define WIN_READDMA_QUEUED		0xC7 /* read sectors using Queued DMA transfers */
+#define WIN_READDMA			0xC8 /* read sectors using DMA transfers */
+#define WIN_WRITEDMA			0xCA /* write sectors using DMA transfers */
+#define WIN_WRITEDMA_QUEUED		0xCC /* write sectors using Queued DMA transfers */
+#define CFA_WRITE_MULTI_WO_ERASE	0xCD /* CFA Write multiple without erase */
+#define WIN_GETMEDIASTATUS		0xDA
+#define WIN_DOORLOCK			0xDE /* lock door on removable drives */
+#define WIN_DOORUNLOCK			0xDF /* unlock door on removable drives */
+#define WIN_STANDBYNOW1			0xE0
+#define WIN_IDLEIMMEDIATE		0xE1 /* force drive to become "ready" */
+#define WIN_STANDBY			0xE2 /* Set device in Standby Mode */
+#define WIN_SETIDLE1			0xE3
+#define WIN_READ_BUFFER			0xE4 /* force read only 1 sector */
+#define WIN_CHECKPOWERMODE1		0xE5
+#define WIN_SLEEPNOW1			0xE6
+#define WIN_FLUSH_CACHE			0xE7
+#define WIN_WRITE_BUFFER		0xE8 /* force write only 1 sector */
+#define WIN_FLUSH_CACHE_EXT		0xEA /* 48-Bit */
+#define WIN_IDENTIFY			0xEC /* ask drive to identify itself	*/
+#define WIN_MEDIAEJECT			0xED
+#define WIN_IDENTIFY_DMA		0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_SETFEATURES			0xEF /* set special drive features */
+#define EXABYTE_ENABLE_NEST		0xF0
+#define WIN_SECURITY_SET_PASS		0xF1
+#define WIN_SECURITY_UNLOCK		0xF2
+#define WIN_SECURITY_ERASE_PREPARE	0xF3
+#define WIN_SECURITY_ERASE_UNIT		0xF4
+#define WIN_SECURITY_FREEZE_LOCK	0xF5
+#define WIN_SECURITY_DISABLE		0xF6
+#define WIN_READ_NATIVE_MAX		0xF8 /* return the native maximum address */
+#define WIN_SET_MAX			0xF9
+#define DISABLE_SEAGATE			0xFB
+
+/* WIN_SMART sub-commands */
+
+#define SMART_READ_VALUES		0xD0
+#define SMART_READ_THRESHOLDS		0xD1
+#define SMART_AUTOSAVE			0xD2
+#define SMART_SAVE			0xD3
+#define SMART_IMMEDIATE_OFFLINE		0xD4
+#define SMART_READ_LOG_SECTOR		0xD5
+#define SMART_WRITE_LOG_SECTOR		0xD6
+#define SMART_WRITE_THRESHOLDS		0xD7
+#define SMART_ENABLE			0xD8
+#define SMART_DISABLE			0xD9
+#define SMART_STATUS			0xDA
+#define SMART_AUTO_OFFLINE		0xDB
+
+/* Password used in TF4 & TF5 executing SMART commands */
+
+#define SMART_LCYL_PASS			0x4F
+#define SMART_HCYL_PASS			0xC2
+
+/* WIN_SETFEATURES sub-commands */
+
+#define SETFEATURES_EN_WCACHE	0x02	/* Enable write cache */
+
+#define SETFEATURES_XFER	0x03	/* Set transfer mode */
+#	define XFER_UDMA_7	0x47	/* 0100|0111 */
+#	define XFER_UDMA_6	0x46	/* 0100|0110 */
+#	define XFER_UDMA_5	0x45	/* 0100|0101 */
+#	define XFER_UDMA_4	0x44	/* 0100|0100 */
+#	define XFER_UDMA_3	0x43	/* 0100|0011 */
+#	define XFER_UDMA_2	0x42	/* 0100|0010 */
+#	define XFER_UDMA_1	0x41	/* 0100|0001 */
+#	define XFER_UDMA_0	0x40	/* 0100|0000 */
+#	define XFER_MW_DMA_2	0x22	/* 0010|0010 */
+#	define XFER_MW_DMA_1	0x21	/* 0010|0001 */
+#	define XFER_MW_DMA_0	0x20	/* 0010|0000 */
+#	define XFER_SW_DMA_2	0x12	/* 0001|0010 */
+#	define XFER_SW_DMA_1	0x11	/* 0001|0001 */
+#	define XFER_SW_DMA_0	0x10	/* 0001|0000 */
+#	define XFER_PIO_4	0x0C	/* 0000|1100 */
+#	define XFER_PIO_3	0x0B	/* 0000|1011 */
+#	define XFER_PIO_2	0x0A	/* 0000|1010 */
+#	define XFER_PIO_1	0x09	/* 0000|1001 */
+#	define XFER_PIO_0	0x08	/* 0000|1000 */
+#	define XFER_PIO_SLOW	0x00	/* 0000|0000 */
+
+#define SETFEATURES_DIS_DEFECT	0x04	/* Disable Defect Management */
+#define SETFEATURES_EN_APM	0x05	/* Enable advanced power management */
+#define SETFEATURES_DIS_MSN	0x31	/* Disable Media Status Notification */
+#define SETFEATURES_EN_AAM	0x42	/* Enable Automatic Acoustic Management */
+#define SETFEATURES_DIS_RLA	0x55	/* Disable read look-ahead feature */
+#define SETFEATURES_EN_RI	0x5D	/* Enable release interrupt */
+#define SETFEATURES_EN_SI	0x5E	/* Enable SERVICE interrupt */
+#define SETFEATURES_DIS_RPOD	0x66	/* Disable reverting to power on defaults */
+#define SETFEATURES_DIS_WCACHE	0x82	/* Disable write cache */
+#define SETFEATURES_EN_DEFECT	0x84	/* Enable Defect Management */
+#define SETFEATURES_DIS_APM	0x85	/* Disable advanced power management */
+#define SETFEATURES_EN_MSN	0x95	/* Enable Media Status Notification */
+#define SETFEATURES_EN_RLA	0xAA	/* Enable read look-ahead feature */
+#define SETFEATURES_PREFETCH	0xAB	/* Sets drive prefetch value */
+#define SETFEATURES_DIS_AAM	0xC2	/* Disable Automatic Acoustic Management */
+#define SETFEATURES_EN_RPOD	0xCC	/* Enable reverting to power on defaults */
+#define SETFEATURES_DIS_RI	0xDD	/* Disable release interrupt */
+#define SETFEATURES_DIS_SI	0xDE	/* Disable SERVICE interrupt */
+
+/* WIN_SECURITY sub-commands */
+
+#define SECURITY_SET_PASSWORD		0xBA
+#define SECURITY_UNLOCK			0xBB
+#define SECURITY_ERASE_PREPARE		0xBC
+#define SECURITY_ERASE_UNIT		0xBD
+#define SECURITY_FREEZE_LOCK		0xBE
+#define SECURITY_DISABLE_PASSWORD	0xBF
+
+
+/* Taskfile related constants.
+ */
+#define IDE_DRIVE_TASK_INVALID		-1
+#define IDE_DRIVE_TASK_NO_DATA		0
+#define IDE_DRIVE_TASK_SET_XFER		1
+
+#define IDE_DRIVE_TASK_IN		2
+
+#define IDE_DRIVE_TASK_OUT		3
+#define IDE_DRIVE_TASK_RAW_WRITE	4
+
+struct hd_drive_task_hdr {
+	u8 feature;
+	u8 sector_count;
+	u8 sector_number;
+	u8 low_cylinder;
+	u8 high_cylinder;
+	u8 device_head;
+} __attribute__((packed));
+
+/*
+ * Define standard taskfile in/out register
+ */
+#define IDE_TASKFILE_STD_OUT_FLAGS	0xFE
+#define IDE_TASKFILE_STD_IN_FLAGS	0xFE
+#define IDE_HOB_STD_OUT_FLAGS		0xC0
+#define IDE_HOB_STD_IN_FLAGS		0xC0
+
+#define TASKFILE_INVALID		0x7fff
+#define TASKFILE_48			0x8000
+
+#define TASKFILE_NO_DATA		0x0000
+
+#define TASKFILE_IN			0x0001
+#define TASKFILE_MULTI_IN		0x0002
+
+#define TASKFILE_OUT			0x0004
+#define TASKFILE_MULTI_OUT		0x0008
+#define TASKFILE_IN_OUT			0x0010
+
+#define TASKFILE_IN_DMA			0x0020
+#define TASKFILE_OUT_DMA		0x0040
+#define TASKFILE_IN_DMAQ		0x0080
+#define TASKFILE_OUT_DMAQ		0x0100
+
+#define TASKFILE_P_IN			0x0200
+#define TASKFILE_P_OUT			0x0400
+#define TASKFILE_P_IN_DMA		0x0800
+#define TASKFILE_P_OUT_DMA		0x1000
+#define TASKFILE_P_IN_DMAQ		0x2000
+#define TASKFILE_P_OUT_DMAQ		0x4000
+
+/* bus states */
+enum {
+	BUSSTATE_OFF = 0,
+	BUSSTATE_ON,
+	BUSSTATE_TRISTATE
+};
+
+/*
+ * Structure returned by HDIO_GET_IDENTITY, as per ANSI NCITS ATA6 rev.1b spec.
+ *
+ * If you change something here, please remember to update fix_driveid() in
+ * ide/probe.c.
+ */
+struct hd_driveid {
+	u16	config;		/* lots of obsolete bit flags */
+	u16	cyls;		/* Obsolete, "physical" cyls */
+	u16	reserved2;	/* reserved (word 2) */
+	u16	heads;		/* Obsolete, "physical" heads */
+	u16	track_bytes;	/* unformatted bytes per track */
+	u16	sector_bytes;	/* unformatted bytes per sector */
+	u16	sectors;	/* Obsolete, "physical" sectors per track */
+	u16	vendor0;	/* vendor unique */
+	u16	vendor1;	/* vendor unique */
+	u16	vendor2;	/* Retired vendor unique */
+	u8	serial_no[20];	/* 0 = not_specified */
+	u16	buf_type;	/* Retired */
+	u16	buf_size;	/* Retired, 512 byte increments
+				 * 0 = not_specified
+				 */
+	u16	ecc_bytes;	/* for r/w long cmds; 0 = not_specified */
+	u8	fw_rev[8];	/* 0 = not_specified */
+	char	model[40];	/* 0 = not_specified */
+	u8	max_multsect;	/* 0=not_implemented */
+	u8	vendor3;	/* vendor unique */
+	u16	dword_io;	/* 0=not_implemented; 1=implemented */
+	u8	vendor4;	/* vendor unique */
+	u8	capability;	/* (upper byte of word 49)
+				 *  3:	IORDYsup
+				 *  2:	IORDYsw
+				 *  1:	LBA
+				 *  0:	DMA
+				 */
+	u16	reserved50;	/* reserved (word 50) */
+	u8	vendor5;	/* Obsolete, vendor unique */
+	u8	tPIO;		/* Obsolete, 0=slow, 1=medium, 2=fast */
+	u8	vendor6;	/* Obsolete, vendor unique */
+	u8	tDMA;		/* Obsolete, 0=slow, 1=medium, 2=fast */
+	u16	field_valid;	/* (word 53)
+				 *  2:	ultra_ok	word  88
+				 *  1:	eide_ok		words 64-70
+				 *  0:	cur_ok		words 54-58
+				 */
+	u16	cur_cyls;	/* Obsolete, logical cylinders */
+	u16	cur_heads;	/* Obsolete, l heads */
+	u16	cur_sectors;	/* Obsolete, l sectors per track */
+	u16	cur_capacity0;	/* Obsolete, l total sectors on drive */
+	u16	cur_capacity1;	/* Obsolete, (2 words, misaligned int)     */
+	u8	multsect;	/* current multiple sector count */
+	u8	multsect_valid;	/* when (bit0==1) multsect is ok */
+	u32	lba_capacity;	/* Obsolete, total number of sectors */
+	u16	dma_1word;	/* Obsolete, single-word dma info */
+	u16	dma_mword;	/* multiple-word dma info */
+	u16	eide_pio_modes; /* bits 0:mode3 1:mode4 */
+	u16	eide_dma_min;	/* min mword dma cycle time (ns) */
+	u16	eide_dma_time;	/* recommended mword dma cycle time (ns) */
+	u16	eide_pio;       /* min cycle time (ns), no IORDY  */
+	u16	eide_pio_iordy; /* min cycle time (ns), with IORDY */
+	u16	words69_70[2];	/* reserved words 69-70
+				 * future command overlap and queuing
+				 */
+	/* HDIO_GET_IDENTITY currently returns only words 0 through 70 */
+	u16	words71_74[4];	/* reserved words 71-74
+				 * for IDENTIFY PACKET DEVICE command
+				 */
+	u16	queue_depth;	/* (word 75)
+				 * 15:5	reserved
+				 *  4:0	Maximum queue depth -1
+				 */
+	u16	words76_79[4];	/* reserved words 76-79 */
+	u16	major_rev_num;	/* (word 80) */
+	u16	minor_rev_num;	/* (word 81) */
+	u16	command_set_1;	/* (word 82) supported
+				 * 15:	Obsolete
+				 * 14:	NOP command
+				 * 13:	READ_BUFFER
+				 * 12:	WRITE_BUFFER
+				 * 11:	Obsolete
+				 * 10:	Host Protected Area
+				 *  9:	DEVICE Reset
+				 *  8:	SERVICE Interrupt
+				 *  7:	Release Interrupt
+				 *  6:	look-ahead
+				 *  5:	write cache
+				 *  4:	PACKET Command
+				 *  3:	Power Management Feature Set
+				 *  2:	Removable Feature Set
+				 *  1:	Security Feature Set
+				 *  0:	SMART Feature Set
+				 */
+	u16	command_set_2;	/* (word 83)
+				 * 15:	Shall be ZERO
+				 * 14:	Shall be ONE
+				 * 13:	FLUSH CACHE EXT
+				 * 12:	FLUSH CACHE
+				 * 11:	Device Configuration Overlay
+				 * 10:	48-bit Address Feature Set
+				 *  9:	Automatic Acoustic Management
+				 *  8:	SET MAX security
+				 *  7:	reserved 1407DT PARTIES
+				 *  6:	SetF sub-command Power-Up
+				 *  5:	Power-Up in Standby Feature Set
+				 *  4:	Removable Media Notification
+				 *  3:	APM Feature Set
+				 *  2:	CFA Feature Set
+				 *  1:	READ/WRITE DMA QUEUED
+				 *  0:	Download MicroCode
+				 */
+	u16	cfsse;		/* (word 84)
+				 * cmd set-feature supported extensions
+				 * 15:	Shall be ZERO
+				 * 14:	Shall be ONE
+				 * 13:3	reserved
+				 *  2:	Media Serial Number Valid
+				 *  1:	SMART selt-test supported
+				 *  0:	SMART error logging
+				 */
+	u16	cfs_enable_1;	/* (word 85)
+				 * command set-feature enabled
+				 * 15:	Obsolete
+				 * 14:	NOP command
+				 * 13:	READ_BUFFER
+				 * 12:	WRITE_BUFFER
+				 * 11:	Obsolete
+				 * 10:	Host Protected Area
+				 *  9:	DEVICE Reset
+				 *  8:	SERVICE Interrupt
+				 *  7:	Release Interrupt
+				 *  6:	look-ahead
+				 *  5:	write cache
+				 *  4:	PACKET Command
+				 *  3:	Power Management Feature Set
+				 *  2:	Removable Feature Set
+				 *  1:	Security Feature Set
+				 *  0:	SMART Feature Set
+				 */
+	u16	cfs_enable_2;	/* (word 86)
+				 * command set-feature enabled
+				 * 15:	Shall be ZERO
+				 * 14:	Shall be ONE
+				 * 13:	FLUSH CACHE EXT
+				 * 12:	FLUSH CACHE
+				 * 11:	Device Configuration Overlay
+				 * 10:	48-bit Address Feature Set
+				 *  9:	Automatic Acoustic Management
+				 *  8:	SET MAX security
+				 *  7:	reserved 1407DT PARTIES
+				 *  6:	SetF sub-command Power-Up
+				 *  5:	Power-Up in Standby Feature Set
+				 *  4:	Removable Media Notification
+				 *  3:	APM Feature Set
+				 *  2:	CFA Feature Set
+				 *  1:	READ/WRITE DMA QUEUED
+				 *  0:	Download MicroCode
+				 */
+	u16	csf_default;	/* (word 87)
+				 * command set-feature default
+				 * 15:	Shall be ZERO
+				 * 14:	Shall be ONE
+				 * 13:3	reserved
+				 *  2:	Media Serial Number Valid
+				 *  1:	SMART selt-test supported
+				 *  0:	SMART error logging
+				 */
+	u16	dma_ultra;	/* (word 88) */
+	u16	word89;		/* reserved (word 89) */
+	u16	word90;		/* reserved (word 90) */
+	u16	CurAPMvalues;	/* current APM values */
+	u16	word92;		/* reserved (word 92) */
+	u16	hw_config;	/* hardware config (word 93)
+				 * 15:
+				 * 14:
+				 * 13:
+				 * 12:
+				 * 11:
+				 * 10:
+				 *  9:
+				 *  8:
+				 *  7:
+				 *  6:
+				 *  5:
+				 *  4:
+				 *  3:
+				 *  2:
+				 *  1:
+				 *  0:
+				 */
+	u16	acoustic;	/* (word 94)
+				 * 15:8	Vendor's recommended value
+				 *  7:0	current value
+				 */
+	u16	words95_99[5];	/* reserved words 95-99 */
+	u64	lba_capacity_2;	/* 48-bit total number of sectors */
+	u16	words104_125[22];/* reserved words 104-125 */
+	u16	last_lun;	/* (word 126) */
+	u16	word127;	/* (word 127) Feature Set
+				 * Removable Media Notification
+				 * 15:2	reserved
+				 *  1:0	00 = not supported
+				 *	01 = supported
+				 *	10 = reserved
+				 *	11 = reserved
+				 */
+	u16	dlf;		/* (word 128)
+				 * device lock function
+				 * 15:9	reserved
+				 *  8	security level 1:max 0:high
+				 *  7:6	reserved
+				 *  5	enhanced erase
+				 *  4	expire
+				 *  3	frozen
+				 *  2	locked
+				 *  1	en/disabled
+				 *  0	capability
+				 */
+	u16	csfo;		/* (word 129)
+				 * current set features options
+				 * 15:4	reserved
+				 *  3:	auto reassign
+				 *  2:	reverting
+				 *  1:	read-look-ahead
+				 *  0:	write cache
+				 */
+	u16	words130_155[26];/* reserved vendor words 130-155 */
+	u16	word156;	/* reserved vendor word 156 */
+	u16	words157_159[3];/* reserved vendor words 157-159 */
+	u16	cfa_power;	/* (word 160) CFA Power Mode
+				 * 15 word 160 supported
+				 * 14 reserved
+				 * 13
+				 * 12
+				 * 11:0
+				 */
+	u16	words161_175[14];/* Reserved for CFA */
+	u16	words176_205[31];/* Current Media Serial Number */
+	u16	words206_254[48];/* reserved words 206-254 */
+	u16	integrity_word;	/* (word 255)
+				 * 15:8 Checksum
+				 *  7:0 Signature
+				 */
+} __attribute__((packed));
+
+#define IDE_NICE_DSC_OVERLAP	(0)	/* per the DSC overlap protocol */
 
 /*
  * Probably not wise to fiddle with these
@@ -105,6 +557,35 @@
 #define GET_ALTSTAT()		IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET])
 #define GET_FEAT()		IN_BYTE(IDE_NSECTOR_REG)
 
+/* Bits of HD_STATUS */
+#define ERR_STAT		0x01
+#define INDEX_STAT		0x02
+#define ECC_STAT		0x04	/* Corrected error */
+#define DRQ_STAT		0x08
+#define SEEK_STAT		0x10
+#define SERVICE_STAT		SEEK_STAT
+#define WRERR_STAT		0x20
+#define READY_STAT		0x40
+#define BUSY_STAT		0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR		0x01	/* Bad address mark */
+#define TRK0_ERR		0x02	/* couldn't find track 0 */
+#define ABRT_ERR		0x04	/* Command aborted */
+#define MCR_ERR			0x08	/* media change request */
+#define ID_ERR			0x10	/* ID field not found */
+#define MC_ERR			0x20	/* media changed */
+#define ECC_ERR			0x40	/* Uncorrectable ECC error */
+#define BBD_ERR			0x80	/* pre-EIDE meaning:  block marked bad */
+#define ICRC_ERR		0x80	/* new meaning:  CRC error during transfer */
+
+/*
+ * sector count bits
+ */
+#define NSEC_CD			0x01
+#define NSEC_IO			0x02
+#define NSEC_REL		0x04
+
 #define BAD_R_STAT		(BUSY_STAT   | ERR_STAT)
 #define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
 #define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
@@ -283,8 +764,6 @@
 	request_queue_t	queue;		/* per device request queue */
 	struct request *rq;		/* current request */
 
-	unsigned long sleep;		/* sleep until this time */
-
 	u8	 retry_pio;		/* retrying dma capable host in pio */
 	u8	 state;			/* retry state */
 
@@ -304,7 +783,6 @@
 	unsigned atapi_overlap	: 1;	/* flag: ATAPI overlap (not supported) */
 	unsigned doorlocking	: 1;	/* flag: for removable only: door lock/unlock works */
 	unsigned autotune	: 2;	/* 1=autotune, 2=noautotune, 0=default */
-	unsigned remap_0_to_1	: 2;	/* 0=remap if ezdrive, 1=remap, 2=noremap */
 	unsigned ata_flash	: 1;	/* 1=present, 0=default */
 	unsigned	addressing;	/* : 2; 0=28-bit, 1=48-bit, 2=64-bit */
 	u8		scsi;		/* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */
@@ -316,7 +794,6 @@
 	u8		mult_count;	/* current multiple sector setting */
 	u8		bad_wstat;	/* used for ignoring WRERR_STAT */
 	u8		nowerr;		/* used for ignoring WRERR_STAT */
-	u8		sect0;		/* offset of first sector for DM6:DDO */
 	u8		head;		/* "real" number of heads */
 	u8		sect;		/* "real" sectors per track */
 	u8		bios_head;	/* BIOS/fdisk/LILO number of heads */
@@ -417,7 +894,7 @@
 	struct pci_dev *pci_dev;		/* for pci chipsets */
 #endif
 	struct ata_device drives[MAX_DRIVES];	/* drive info */
-	struct gendisk *gd;			/* gendisk structure */
+	struct gendisk *gd[MAX_DRIVES];		/* gendisk structure */
 
 	/*
 	 * Routines to tune PIO and DMA mode for drives.
@@ -466,6 +943,8 @@
 	void (*udma_timeout) (struct ata_device *);
 	void (*udma_irq_lost) (struct ata_device *);
 
+	unsigned long	seg_boundary_mask;
+	unsigned int	max_segment_size;
 	unsigned int	*dmatable_cpu;	/* dma physical region descriptor table (cpu view) */
 	dma_addr_t	dmatable_dma;	/* dma physical region descriptor table (dma view) */
 	struct scatterlist *sg_table;	/* Scatter-gather list used to build the above */
@@ -665,23 +1144,23 @@
  */
 extern int ideprobe_init(void);
 #ifdef CONFIG_BLK_DEV_IDEDISK
-extern int idedisk_init (void);
+extern int idedisk_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_IDECD
-extern int ide_cdrom_init (void);
+extern int ide_cdrom_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_IDETAPE
-extern int idetape_init (void);
+extern int idetape_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_IDEFLOPPY
-extern int idefloppy_init (void);
+extern int idefloppy_init(void);
 #endif
 #ifdef CONFIG_BLK_DEV_IDESCSI
-extern int idescsi_init (void);
+extern int idescsi_init(void);
 #endif
 
-extern int ide_register_subdriver(struct ata_device *, struct ata_operations *);
-extern int ide_unregister_subdriver(struct ata_device *drive);
+extern int ata_register_device(struct ata_device *, struct ata_operations *);
+extern int ata_unregister_device(struct ata_device *drive);
 extern int ata_revalidate(kdev_t i_rdev);
 extern void ide_driver_module(void);
 
diff -Nru a/include/linux/input.h b/include/linux/input.h
--- a/include/linux/input.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/input.h	Thu Aug  1 14:17:40 2002
@@ -41,9 +41,9 @@
 
 struct input_event {
 	struct timeval time;
-	unsigned short type;
-	unsigned short code;
-	unsigned int value;
+	__u16 type;
+	__u16 code;
+	__s32 value;
 };
 
 /*
@@ -63,6 +63,14 @@
 	__u16 version;
 };
 
+struct input_absinfo {
+	__s32 value;
+	__s32 minimum;
+	__s32 maximum;
+	__s32 fuzz;
+	__s32 flat;
+};
+
 #define EVIOCGVERSION		_IOR('E', 0x01, int)			/* get driver version */
 #define EVIOCGID		_IOR('E', 0x02, struct input_id)	/* get device ID */
 #define EVIOCGREP		_IOR('E', 0x03, int[2])			/* get repeat settings */
@@ -79,8 +87,8 @@
 #define EVIOCGSND(len)		_IOC(_IOC_READ, 'E', 0x1a, len)		/* get all sounds status */
 
 #define EVIOCGBIT(ev,len)	_IOC(_IOC_READ, 'E', 0x20 + ev, len)	/* get event bits */
-#define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, int[5])		/* get abs value/limits */
-#define EVIOCSABS(abs)		_IOW('E', 0xc0 + abs, int[5])		/* set abs value/limits */
+#define EVIOCGABS(abs)		_IOR('E', 0x40 + abs, struct input_absinfo)		/* get abs value/limits */
+#define EVIOCSABS(abs)		_IOW('E', 0xc0 + abs, struct input_absinfo)		/* set abs value/limits */
 
 #define EVIOCSFF		_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))	/* send a force effect to a force feedback device */
 #define EVIOCRMFF		_IOW('E', 0x81, int)			/* Erase a force effect */
@@ -473,11 +481,11 @@
 #define KEY_RESTART		0x198
 #define KEY_SLOW		0x199
 #define KEY_SHUFFLE		0x19a
-#define KEY_BREAK		0x1ab
+#define KEY_BREAK		0x19b
 #define KEY_PREVIOUS		0x19c
 #define KEY_DIGITS		0x19d
 #define KEY_TEEN		0x19e
-#define KEY_TWEN		0x1af
+#define KEY_TWEN		0x19f
 
 #define KEY_MAX			0x1ff
 
diff -Nru a/include/linux/jffs2.h b/include/linux/jffs2.h
--- a/include/linux/jffs2.h	Thu Aug  1 14:17:41 2002
+++ b/include/linux/jffs2.h	Thu Aug  1 14:17:41 2002
@@ -5,33 +5,10 @@
  *
  * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  *
- * The original JFFS, from which the design for JFFS2 was derived,
- * was designed and implemented by Axis Communications AB.
+ * For licensing information, see the file 'LICENCE' in the 
+ * jffs2 directory.
  *
- * The contents of this file are subject to the Red Hat eCos Public
- * License Version 1.1 (the "Licence"); you may not use this file
- * except in compliance with the Licence.  You may obtain a copy of
- * the Licence at http://www.redhat.com/
- *
- * Software distributed under the Licence is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing rights and
- * limitations under the Licence.
- *
- * The Original Code is JFFS2 - Journalling Flash File System, version 2
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License version 2 (the "GPL"), in
- * which case the provisions of the GPL are applicable instead of the
- * above.  If you wish to allow the use of your version of this file
- * only under the terms of the GPL and not to allow others to use your
- * version of this file under the RHEPL, indicate your decision by
- * deleting the provisions above and replace them with the notice and
- * other provisions required by the GPL.  If you do not delete the
- * provisions above, a recipient may use your version of this file
- * under either the RHEPL or the GPL.
- *
- * $Id: jffs2.h,v 1.23 2002/02/21 17:03:45 dwmw2 Exp $
+ * $Id: jffs2.h,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $
  *
  */
 
diff -Nru a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h
--- a/include/linux/jffs2_fs_sb.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/jffs2_fs_sb.h	Thu Aug  1 14:17:36 2002
@@ -1,16 +1,15 @@
-/* $Id: jffs2_fs_sb.h,v 1.26 2002/03/17 10:18:42 dwmw2 Exp $ */
+/* $Id: jffs2_fs_sb.h,v 1.32 2002/07/23 14:35:34 dwmw2 Exp $ */
 
 #ifndef _JFFS2_FS_SB
 #define _JFFS2_FS_SB
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
+#include <linux/tqueue.h>
 #include <linux/completion.h>
 #include <asm/semaphore.h>
 #include <linux/list.h>
 
-#define INOCACHE_HASHSIZE 14
-
 #define JFFS2_SB_FLAG_RO 1
 #define JFFS2_SB_FLAG_MOUNTING 2
 
@@ -33,6 +32,9 @@
 					   out-of-order writing of nodes.
 					   And GC.
 					*/
+	uint32_t cleanmarker_size;	/* Size of an _inline_ CLEANMARKER
+					 (i.e. zero for OOB CLEANMARKER */
+
 	uint32_t flash_size;
 	uint32_t used_size;
 	uint32_t dirty_size;
@@ -52,6 +54,7 @@
 	struct jffs2_eraseblock *gcblock;	/* The block we're currently garbage-collecting */
 
 	struct list_head clean_list;		/* Blocks 100% full of clean data */
+	struct list_head very_dirty_list;	/* Blocks with lots of dirty space */
 	struct list_head dirty_list;		/* Blocks with some dirty space */
 	struct list_head erasable_list;		/* Blocks which are completely dirty, and need erasing */
 	struct list_head erasable_pending_wbuf_list;	/* Blocks which need erasing but only after the current wbuf is flushed */
@@ -66,10 +69,8 @@
 						   against erase completion handler */
 	wait_queue_head_t erase_wait;		/* For waiting for erases to complete */
 
-	struct jffs2_inode_cache *inocache_list[INOCACHE_HASHSIZE];
+	struct jffs2_inode_cache **inocache_list;
 	spinlock_t inocache_lock;
-	/* This _really_ speeds up mounts. */
-	struct jffs2_inode_cache *inocache_last;
 	
 	/* Sem to allow jffs2_garbage_collect_deletion_dirent to
 	   drop the erase_completion_lock while it's holding a pointer 
@@ -81,6 +82,8 @@
 	uint32_t wbuf_ofs;
 	uint32_t wbuf_len;
 	uint32_t wbuf_pagesize;
+	struct tq_struct wbuf_task;		/* task for timed wbuf flush */
+	struct timer_list wbuf_timer;		/* timer for flushing wbuf */
 
 	/* OS-private pointer for getting back to master superblock info */
 	void *os_priv;
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/list.h	Thu Aug  1 14:17:36 2002
@@ -156,9 +156,7 @@
  */
 static inline void list_splice(list_t *list, list_t *head)
 {
-	list_t *first = list->next;
-
-	if (first != list)
+	if (!list_empty(list))
 		__list_splice(list, head);
 }
 
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/mm.h	Thu Aug  1 14:17:36 2002
@@ -103,8 +103,9 @@
 #define VM_DONTCOPY	0x00020000      /* Do not copy this vma on fork */
 #define VM_DONTEXPAND	0x00040000	/* Cannot expand with mremap() */
 #define VM_RESERVED	0x00080000	/* Don't unmap it from swap_out */
+#define VM_ACCOUNT	0x00100000	/* Is a VM accounted object */
 
-#define VM_STACK_FLAGS	(0x00000100 | VM_DATA_DEFAULT_FLAGS)
+#define VM_STACK_FLAGS	(0x00000100 | VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT)
 
 #define VM_READHINTMASK			(VM_SEQ_READ | VM_RAND_READ)
 #define VM_ClearReadHint(v)		(v)->vm_flags &= ~VM_READHINTMASK
@@ -149,12 +150,12 @@
  * TODO: make this structure smaller, it could be as small as 32 bytes.
  */
 struct page {
+	unsigned long flags;		/* atomic flags, some possibly
+					   updated asynchronously */
+	atomic_t count;			/* Usage count, see below. */
 	struct list_head list;		/* ->mapping has some page lists. */
 	struct address_space *mapping;	/* The inode (or ...) we belong to. */
 	unsigned long index;		/* Our offset within mapping. */
-	atomic_t count;			/* Usage count, see below. */
-	unsigned long flags;		/* atomic flags, some possibly
-					   updated asynchronously */
 	struct list_head lru;		/* Pageout list, eg. active_list;
 					   protected by pagemap_lru_lock !! */
 	union {
@@ -327,11 +328,10 @@
 extern struct page *mem_map;
 
 extern void show_free_areas(void);
-extern void show_free_areas_node(pg_data_t *pgdat);
 
 extern int fail_writepage(struct page *);
 struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int unused);
-struct file *shmem_file_setup(char * name, loff_t size);
+struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags);
 extern void shmem_lock(struct file * file, int lock);
 extern int shmem_zero_setup(struct vm_area_struct *);
 
@@ -401,8 +401,6 @@
 extern int can_share_swap_page(struct page *);
 extern int remove_exclusive_swap_page(struct page *);
 
-extern void __free_pte(pte_t);
-
 /* mmap.c */
 extern void lock_vma_mappings(struct vm_area_struct *);
 extern void unlock_vma_mappings(struct vm_area_struct *);
@@ -472,31 +470,8 @@
 void page_cache_readaround(struct file *file, unsigned long offset);
 void handle_ra_miss(struct file *file);
 
-/* vma is the first one with  address < vma->vm_end,
- * and even  address < vma->vm_start. Have to extend vma. */
-static inline int expand_stack(struct vm_area_struct * vma, unsigned long address)
-{
-	unsigned long grow;
-
-	/*
-	 * vma->vm_start/vm_end cannot change under us because the caller is required
-	 * to hold the mmap_sem in write mode. We need to get the spinlock only
-	 * before relocating the vma range ourself.
-	 */
-	address &= PAGE_MASK;
-	grow = (vma->vm_start - address) >> PAGE_SHIFT;
-	if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
-	    ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
-		return -ENOMEM;
-	spin_lock(&vma->vm_mm->page_table_lock);
-	vma->vm_start = address;
-	vma->vm_pgoff -= grow;
-	vma->vm_mm->total_vm += grow;
-	if (vma->vm_flags & VM_LOCKED)
-		vma->vm_mm->locked_vm += grow;
-	spin_unlock(&vma->vm_mm->page_table_lock);
-	return 0;
-}
+/* Do stack extension */
+extern int expand_stack(struct vm_area_struct * vma, unsigned long address);
 
 /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
 extern struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr);
diff -Nru a/include/linux/mman.h b/include/linux/mman.h
--- a/include/linux/mman.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/mman.h	Thu Aug  1 14:17:36 2002
@@ -6,4 +6,7 @@
 #define MREMAP_MAYMOVE	1
 #define MREMAP_FIXED	2
 
+extern int vm_enough_memory(long pages);
+extern void vm_unacct_memory(long pages);
+
 #endif /* _LINUX_MMAN_H */
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/mmzone.h	Thu Aug  1 14:17:36 2002
@@ -136,7 +136,7 @@
 	unsigned long node_start_mapnr;
 	unsigned long node_size;
 	int node_id;
-	struct pglist_data *node_next;
+	struct pglist_data *pgdat_next;
 } pg_data_t;
 
 extern int numnodes;
@@ -162,6 +162,57 @@
   struct page *pmap);
 
 extern pg_data_t contig_page_data;
+
+/**
+ * for_each_pgdat - helper macro to iterate over all nodes
+ * @pgdat - pointer to a pg_data_t variable
+ *
+ * Meant to help with common loops of the form
+ * pgdat = pgdat_list;
+ * while(pgdat) {
+ * 	...
+ * 	pgdat = pgdat->pgdat_next;
+ * }
+ */
+#define for_each_pgdat(pgdat) \
+	for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
+
+/*
+ * next_zone - helper magic for for_each_zone()
+ * Thanks to William Lee Irwin III for this piece of ingenuity.
+ */
+static inline zone_t * next_zone(zone_t * zone)
+{
+	pg_data_t *pgdat = zone->zone_pgdat;
+
+	if (zone - pgdat->node_zones < MAX_NR_ZONES - 1)
+		zone++;
+	else if (pgdat->pgdat_next) {
+		pgdat = pgdat->pgdat_next;
+		zone = pgdat->node_zones;
+	} else
+		zone = NULL;
+
+	return zone;
+}
+
+/**
+ * for_each_zone - helper macro to iterate over all memory zones
+ * @zone - pointer to zone_t variable
+ *
+ * The user only needs to declare the zone variable, for_each_zone
+ * fills it in. This basically means for_each_zone() is an
+ * easier to read version of this piece of code:
+ *
+ * for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next)
+ * 	for (i = 0; i < MAX_NR_ZONES; ++i) {
+ * 		zone_t * z = pgdat->node_zones + i;
+ * 		...
+ * 	}
+ * }
+ */
+#define for_each_zone(zone) \
+	for (zone = pgdat_list->node_zones; zone; zone = next_zone(zone))
 
 #ifndef CONFIG_DISCONTIGMEM
 
diff -Nru a/include/linux/n_r3964.h b/include/linux/n_r3964.h
--- a/include/linux/n_r3964.h	Thu Aug  1 14:17:41 2002
+++ b/include/linux/n_r3964.h	Thu Aug  1 14:17:41 2002
@@ -13,6 +13,12 @@
  * L. Haag
  *
  * $Log: r3964.h,v $
+ * Revision 1.3  2001/03/18 13:02:24  dwmw2
+ * Fix timer usage, use spinlocks properly.
+ *
+ * Revision 1.2  2001/03/18 12:53:15  dwmw2
+ * Merge changes in 2.4.2
+ *
  * Revision 1.1.1.1  1998/10/13 16:43:14  dwmw2
  * This'll screw the version control
  *
@@ -103,8 +109,9 @@
 struct r3964_message;
 
 struct r3964_client_info {
+	spinlock_t     lock;
 	pid_t          pid;
-    unsigned int   sig_flags;
+	unsigned int   sig_flags;
 
 	struct r3964_client_info *next;
 
@@ -186,6 +193,7 @@
 
 
 struct r3964_info {
+	spinlock_t     lock;
 	struct tty_struct *tty;
 	unsigned char priority;
 	unsigned char *rx_buf;            /* ring buffer */
@@ -209,11 +217,8 @@
 	unsigned int state;
 	unsigned int flags;
 
-	int count_down;
-    int nRetry;
-
-    struct tq_struct bh_1;
-    struct tq_struct bh_2;
+	struct timer_list tmr;
+	int nRetry;
 };
 
 #endif	
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/nfs_fs.h	Thu Aug  1 14:17:40 2002
@@ -225,8 +225,15 @@
 
 #define NFS_FILEID(inode)		(NFS_I(inode)->fileid)
 
-/* Inode Flags */
-#define NFS_USE_READDIRPLUS(inode)	((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0)
+static inline int nfs_server_capable(struct inode *inode, int cap)
+{
+	return NFS_SERVER(inode)->caps & cap;
+}
+
+static inline int NFS_USE_READDIRPLUS(struct inode *inode)
+{
+	return NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS;
+}
 
 static inline
 loff_t page_offset(struct page *page)
diff -Nru a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
--- a/include/linux/nfs_fs_sb.h	Thu Aug  1 14:17:41 2002
+++ b/include/linux/nfs_fs_sb.h	Thu Aug  1 14:17:41 2002
@@ -10,6 +10,7 @@
 	struct rpc_clnt *	client;		/* RPC client handle */
 	struct nfs_rpc_ops *	rpc_ops;	/* NFS protocol vector */
 	int			flags;		/* various flags */
+	unsigned int		caps;		/* server capabilities */
 	unsigned int		rsize;		/* read size */
 	unsigned int		rpages;		/* read size (in pages) */
 	unsigned int		wsize;		/* write size */
@@ -30,5 +31,8 @@
 	struct nfs_fh		fh;
 	struct sockaddr_in	addr;
 };
+
+/* Server capabilities */
+#define NFS_CAP_READDIRPLUS	(1)
 
 #endif
diff -Nru a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
--- a/include/linux/nfs_xdr.h	Thu Aug  1 14:17:39 2002
+++ b/include/linux/nfs_xdr.h	Thu Aug  1 14:17:39 2002
@@ -27,6 +27,7 @@
 	__u64			atime;
 	__u64			mtime;
 	__u64			ctime;
+	unsigned long		timestamp;
 };
 
 #define NFS_ATTR_WCC		0x0001		/* pre-op WCC data    */
@@ -109,8 +110,8 @@
 	const char *		name;
 	unsigned int		len;
 	int			eof;
-	struct nfs_fh		fh;
-	struct nfs_fattr	fattr;
+	struct nfs_fh *		fh;
+	struct nfs_fattr *	fattr;
 };
 
 /*
diff -Nru a/include/linux/page-flags.h b/include/linux/page-flags.h
--- a/include/linux/page-flags.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/page-flags.h	Thu Aug  1 14:17:36 2002
@@ -79,8 +79,7 @@
 	unsigned long nr_active;	/* on active_list LRU */
 	unsigned long nr_inactive;	/* on inactive_list LRU */
 	unsigned long nr_page_table_pages;
-	unsigned long nr_pte_chain_pages;
-	unsigned long used_pte_chains_bytes;
+	unsigned long nr_reverse_maps;
 } ____cacheline_aligned_in_smp page_states[NR_CPUS];
 
 extern void get_page_state(struct page_state *ret);
@@ -241,16 +240,20 @@
 	 * attempt to acquire the lock bit.
 	 */
 	preempt_disable();
+#ifdef CONFIG_SMP
 	while (test_and_set_bit(PG_chainlock, &page->flags)) {
 		while (test_bit(PG_chainlock, &page->flags))
 			cpu_relax();
 	}
+#endif
 }
 
 static inline void pte_chain_unlock(struct page *page)
 {
+#ifdef CONFIG_SMP
 	smp_mb__before_clear_bit();
 	clear_bit(PG_chainlock, &page->flags);
+#endif
 	preempt_enable();
 }
 
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/pci.h	Thu Aug  1 14:17:40 2002
@@ -567,6 +567,10 @@
 int pci_write_config_word(struct pci_dev *dev, int where, u16 val);
 int pci_write_config_dword(struct pci_dev *dev, int where, u32 val);
 
+extern spinlock_t pci_lock;
+
+extern spinlock_t pci_lock;
+
 int pci_enable_device(struct pci_dev *dev);
 void pci_disable_device(struct pci_dev *dev);
 void pci_set_master(struct pci_dev *dev);
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/pci_ids.h	Thu Aug  1 14:17:40 2002
@@ -506,13 +506,18 @@
 #define PCI_DEVICE_ID_HP_TACHLITE	0x1029
 #define PCI_DEVICE_ID_HP_J2585A		0x1030
 #define PCI_DEVICE_ID_HP_J2585B		0x1031
-#define PCI_DEVICE_ID_HP_SAS		0x1048
-#define PCI_DEVICE_ID_HP_DIVA1		0x1049
-#define PCI_DEVICE_ID_HP_DIVA2		0x104A
-#define PCI_DEVICE_ID_HP_SP2_0		0x104B
+#define PCI_DEVICE_ID_HP_DIVA		0x1048
+#define PCI_DEVICE_ID_HP_DIVA_TOSCA1	0x1049
+#define PCI_DEVICE_ID_HP_DIVA_TOSCA2	0x104A
+#define PCI_DEVICE_ID_HP_DIVA_MAESTRO	0x104B
+#define PCI_DEVICE_ID_HP_DIVA_HALFDOME	0x1223
+#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE	0x1226
+#define PCI_DEVICE_ID_HP_DIVA_POWERBAR	0x1227
 #define PCI_DEVICE_ID_HP_ZX1_SBA	0x1229
 #define PCI_DEVICE_ID_HP_ZX1_IOC	0x122a
 #define PCI_DEVICE_ID_HP_ZX1_LBA	0x122e
+#define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
+#define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
diff -Nru a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h
--- a/include/linux/rwsem-spinlock.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/rwsem-spinlock.h	Thu Aug  1 14:17:40 2002
@@ -54,9 +54,12 @@
 
 extern void FASTCALL(init_rwsem(struct rw_semaphore *sem));
 extern void FASTCALL(__down_read(struct rw_semaphore *sem));
+extern int FASTCALL(__down_read_trylock(struct rw_semaphore *sem));
 extern void FASTCALL(__down_write(struct rw_semaphore *sem));
+extern int FASTCALL(__down_write_trylock(struct rw_semaphore *sem));
 extern void FASTCALL(__up_read(struct rw_semaphore *sem));
 extern void FASTCALL(__up_write(struct rw_semaphore *sem));
+extern void FASTCALL(__downgrade_write(struct rw_semaphore *sem));
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_RWSEM_SPINLOCK_H */
diff -Nru a/include/linux/rwsem.h b/include/linux/rwsem.h
--- a/include/linux/rwsem.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/rwsem.h	Thu Aug  1 14:17:40 2002
@@ -46,6 +46,18 @@
 }
 
 /*
+ * trylock for reading -- returns 1 if successful, 0 if contention
+ */
+static inline int down_read_trylock(struct rw_semaphore *sem)
+{
+	int ret;
+	rwsemtrace(sem,"Entering down_read_trylock");
+	ret = __down_read_trylock(sem);
+	rwsemtrace(sem,"Leaving down_read_trylock");
+	return ret;
+}
+
+/*
  * lock for writing
  */
 static inline void down_write(struct rw_semaphore *sem)
@@ -56,6 +68,18 @@
 }
 
 /*
+ * trylock for writing -- returns 1 if successful, 0 if contention
+ */
+static inline int down_write_trylock(struct rw_semaphore *sem)
+{
+	int ret;
+	rwsemtrace(sem,"Entering down_write_trylock");
+	ret = __down_write_trylock(sem);
+	rwsemtrace(sem,"Leaving down_write_trylock");
+	return ret;
+}
+
+/*
  * release a read lock
  */
 static inline void up_read(struct rw_semaphore *sem)
@@ -84,7 +108,6 @@
 	__downgrade_write(sem);
 	rwsemtrace(sem,"Leaving downgrade_write");
 }
-
 
 #endif /* __KERNEL__ */
 #endif /* _LINUX_RWSEM_H */
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/sched.h	Thu Aug  1 14:17:36 2002
@@ -393,7 +393,7 @@
 #define PF_FREEZE	0x00010000	/* this task should be frozen for suspend */
 #define PF_IOTHREAD	0x00020000	/* this thread is needed for doing I/O to swap */
 #define PF_FROZEN	0x00040000	/* frozen for system suspend */
-#define PF_INVALIDATE	0x00080000	/* debug: unmounting an fs. killme. */
+
 /*
  * Ptrace flags
  */
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/security.h	Thu Aug  1 14:17:36 2002
@@ -407,7 +407,6 @@
  *	@file contains the file structure.
  *	@cmd contains the posix-translated lock operation to perform
  *	(e.g. F_RDLCK, F_WRLCK).
- *	@blocking indicates if the request is for a blocking lock.
  *	Return 0 if permission is granted.
  * @file_fcntl:
  *	Check permission before allowing the file operation specified by @cmd
@@ -753,7 +752,7 @@
 	int (*file_mmap) (struct file * file,
 			  unsigned long prot, unsigned long flags);
 	int (*file_mprotect) (struct vm_area_struct * vma, unsigned long prot);
-	int (*file_lock) (struct file * file, unsigned int cmd, int blocking);
+	int (*file_lock) (struct file * file, unsigned int cmd);
 	int (*file_fcntl) (struct file * file, unsigned int cmd,
 			   unsigned long arg);
 	int (*file_set_fowner) (struct file * file);
diff -Nru a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h
--- a/include/linux/shmem_fs.h	Thu Aug  1 14:17:41 2002
+++ b/include/linux/shmem_fs.h	Thu Aug  1 14:17:41 2002
@@ -16,7 +16,7 @@
 	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* for the first blocks */
 	void		      **i_indirect; /* indirect blocks */
 	unsigned long		swapped;
-	int			locked;     /* into memory */
+	unsigned long		flags;
 	struct list_head	list;
 	struct inode		vfs_inode;
 };
diff -Nru a/include/linux/signal.h b/include/linux/signal.h
--- a/include/linux/signal.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/signal.h	Thu Aug  1 14:17:36 2002
@@ -221,6 +221,7 @@
 extern long do_sigpending(void *, unsigned long);
 
 #ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
+struct pt_regs;
 extern int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs);
 #endif
 
diff -Nru a/include/linux/slab.h b/include/linux/slab.h
--- a/include/linux/slab.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/slab.h	Thu Aug  1 14:17:40 2002
@@ -57,6 +57,7 @@
 extern int kmem_cache_shrink(kmem_cache_t *);
 extern void *kmem_cache_alloc(kmem_cache_t *, int);
 extern void kmem_cache_free(kmem_cache_t *, void *);
+extern unsigned int kmem_cache_size(kmem_cache_t *);
 
 extern void *kmalloc(size_t, int);
 extern void kfree(const void *);
diff -Nru a/include/linux/smp.h b/include/linux/smp.h
--- a/include/linux/smp.h	Thu Aug  1 14:17:40 2002
+++ b/include/linux/smp.h	Thu Aug  1 14:17:40 2002
@@ -101,9 +101,13 @@
 #define this_cpu(var)				var
 
 /* Need to know about CPUs going up/down? */
-#define register_cpu_notifier(nb) 0
-#define unregister_cpu_notifier(nb) do { } while(0)
-
+static inline int register_cpu_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline void unregister_cpu_notifier(struct notifier_block *nb)
+{
+}
 #endif /* !SMP */
 
 #define get_cpu()		({ preempt_disable(); smp_processor_id(); })
diff -Nru a/include/linux/swap.h b/include/linux/swap.h
--- a/include/linux/swap.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/swap.h	Thu Aug  1 14:17:36 2002
@@ -176,10 +176,7 @@
 /* linux/mm/page_alloc.c */
 
 /* linux/mm/swap_state.c */
-#define SWAP_CACHE_INFO
-#ifdef SWAP_CACHE_INFO
 extern void show_swap_cache_info(void);
-#endif
 extern int add_to_swap_cache(struct page *, swp_entry_t);
 extern int add_to_swap(struct page *);
 extern void __delete_from_swap_cache(struct page *page);
diff -Nru a/include/linux/swapctl.h b/include/linux/swapctl.h
--- a/include/linux/swapctl.h	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,13 +0,0 @@
-#ifndef _LINUX_SWAPCTL_H
-#define _LINUX_SWAPCTL_H
-
-typedef struct pager_daemon_v1
-{
-	unsigned int	tries_base;
-	unsigned int	tries_min;
-	unsigned int	swap_cluster;
-} pager_daemon_v1;
-typedef pager_daemon_v1 pager_daemon_t;
-extern pager_daemon_t pager_daemon;
-
-#endif /* _LINUX_SWAPCTL_H */
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/sysctl.h	Thu Aug  1 14:17:36 2002
@@ -136,12 +136,12 @@
 	VM_UNUSED1=1,		/* was: struct: Set vm swapping control */
 	VM_UNUSED2=2,		/* was; int: Linear or sqrt() swapout for hogs */
 	VM_UNUSED3=3,		/* was: struct: Set free page thresholds */
-	VM_BDFLUSH_UNUSED=4,	/* Spare */
+	VM_UNUSED4=4,		/* Spare */
 	VM_OVERCOMMIT_MEMORY=5,	/* Turn off the virtual memory safety limit */
-	VM_UNUSED4=6,		/* was: struct: Set buffer memory thresholds */
-	VM_UNUSED5=7,		/* was: struct: Set cache memory thresholds */
-	VM_PAGERDAEMON=8,	/* struct: Control kswapd behaviour */
-	VM_UNUSED6=9,		/* was: struct: Set page table cache parameters */
+	VM_UNUSED5=6,		/* was: struct: Set buffer memory thresholds */
+	VM_UNUSED7=7,		/* was: struct: Set cache memory thresholds */
+	VM_UNUSED8=8,		/* was: struct: Control kswapd behaviour */
+	VM_UNUSED9=9,		/* was: struct: Set page table cache parameters */
 	VM_PAGE_CLUSTER=10,	/* int: set number of pages to swap together */
 	VM_DIRTY_BACKGROUND=11,	/* dirty_background_ratio */
 	VM_DIRTY_ASYNC=12,	/* dirty_async_ratio */
@@ -149,6 +149,7 @@
 	VM_DIRTY_WB_CS=14,	/* dirty_writeback_centisecs */
 	VM_DIRTY_EXPIRE_CS=15,	/* dirty_expire_centisecs */
 	VM_NR_PDFLUSH_THREADS=16, /* nr_pdflush_threads */
+	VM_OVERCOMMIT_RATIO=17, /* percent of RAM to allow overcommit in */
 };
 
 
@@ -171,7 +172,6 @@
 	NET_TR=14,
 	NET_DECNET=15,
 	NET_ECONET=16,
-	NET_KHTTPD=17
 };
 
 /* /proc/sys/kernel/random */
@@ -491,23 +491,6 @@
 	NET_DECNET_CONF = 10,
 	NET_DECNET_NO_FC_MAX_CWND = 11,
 	NET_DECNET_DEBUG_LEVEL = 255
-};
-
-/* /proc/sys/net/khttpd/ */
-enum {
-	NET_KHTTPD_DOCROOT	= 1,
-	NET_KHTTPD_START	= 2,
-	NET_KHTTPD_STOP		= 3,
-	NET_KHTTPD_UNLOAD	= 4,
-	NET_KHTTPD_CLIENTPORT	= 5,
-	NET_KHTTPD_PERMREQ	= 6,
-	NET_KHTTPD_PERMFORBID	= 7,
-	NET_KHTTPD_LOGGING	= 8,
-	NET_KHTTPD_SERVERPORT	= 9,
-	NET_KHTTPD_DYNAMICSTRING= 10,
-	NET_KHTTPD_SLOPPYMIME   = 11,
-	NET_KHTTPD_THREADS	= 12,
-	NET_KHTTPD_MAXCONNECT	= 13
 };
 
 /* /proc/sys/net/decnet/conf/<dev> */
diff -Nru a/include/linux/timer.h b/include/linux/timer.h
--- a/include/linux/timer.h	Thu Aug  1 14:17:36 2002
+++ b/include/linux/timer.h	Thu Aug  1 14:17:36 2002
@@ -2,6 +2,7 @@
 #define _LINUX_TIMER_H
 
 #include <linux/config.h>
+#include <linux/stddef.h>
 #include <linux/list.h>
 
 /*
diff -Nru a/init/do_mounts.c b/init/do_mounts.c
--- a/init/do_mounts.c	Thu Aug  1 14:17:40 2002
+++ b/init/do_mounts.c	Thu Aug  1 14:17:40 2002
@@ -356,11 +356,12 @@
 	if (!do_devfs)
 		return sys_mknod(name, S_IFBLK|0600, dev);
 
-	handle = devfs_find_handle(NULL, !dev ? devfs_name : NULL,
-				MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1);
+	handle = devfs_get_handle(NULL, !dev ? devfs_name : NULL,
+				  MAJOR(dev), MINOR(dev), DEVFS_SPECIAL_BLK, 1);
 	if (!handle)
 		return -1;
 	n = devfs_generate_path(handle, path + 5, sizeof (path) - 5);
+	devfs_put(handle);
 	if (n < 0)
 		return -1;
 	return sys_symlink(path + n + 5, name);
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	Thu Aug  1 14:17:36 2002
+++ b/init/main.c	Thu Aug  1 14:17:36 2002
@@ -70,7 +70,7 @@
 extern void sysctl_init(void);
 extern void signals_init(void);
 extern void buffer_init(void);
-
+extern void pte_chain_init(void);
 extern void radix_tree_init(void);
 extern void free_initmem(void);
 
@@ -432,7 +432,7 @@
 	mem_init();
 	kmem_cache_sizes_init();
 	pgtable_cache_init();
-
+	pte_chain_init();
 	mempages = num_physpages;
 
 	fork_init(mempages);
@@ -524,6 +524,17 @@
 	do_initcalls();
 }
 
+static void do_pre_smp_initcalls(void)
+{
+	extern int spawn_ksoftirqd(void);
+#ifdef CONFIG_SMP
+	extern int migration_init(void);
+
+	migration_init();
+#endif
+	spawn_ksoftirqd();
+}
+
 extern void prepare_namespace(void);
 
 static int init(void * unused)
@@ -533,6 +544,9 @@
 	lock_kernel();
 	/* Sets up cpus_possible() */
 	smp_prepare_cpus(max_cpus);
+
+	do_pre_smp_initcalls();
+
 	smp_init();
 	do_basic_setup();
 
diff -Nru a/ipc/shm.c b/ipc/shm.c
--- a/ipc/shm.c	Thu Aug  1 14:17:40 2002
+++ b/ipc/shm.c	Thu Aug  1 14:17:40 2002
@@ -186,7 +186,7 @@
 	shp->shm_flags = (shmflg & S_IRWXUGO);
 
 	sprintf (name, "SYSV%08x", key);
-	file = shmem_file_setup(name, size);
+	file = shmem_file_setup(name, size, VM_ACCOUNT);
 	error = PTR_ERR(file);
 	if (IS_ERR(file))
 		goto no_file;
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Thu Aug  1 14:17:36 2002
+++ b/kernel/fork.c	Thu Aug  1 14:17:36 2002
@@ -23,6 +23,7 @@
 #include <linux/personality.h>
 #include <linux/file.h>
 #include <linux/binfmts.h>
+#include <linux/mman.h>
 #include <linux/fs.h>
 #include <linux/security.h>
 
@@ -181,6 +182,7 @@
 {
 	struct vm_area_struct * mpnt, *tmp, **pprev;
 	int retval;
+	unsigned long charge = 0;
 
 	flush_cache_mm(current->mm);
 	mm->locked_vm = 0;
@@ -208,6 +210,12 @@
 		retval = -ENOMEM;
 		if(mpnt->vm_flags & VM_DONTCOPY)
 			continue;
+		if (mpnt->vm_flags & VM_ACCOUNT) {
+			unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+			if (!vm_enough_memory(len))
+				goto fail_nomem;
+			charge += len;
+		}
 		tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 		if (!tmp)
 			goto fail_nomem;
@@ -248,9 +256,12 @@
 	retval = 0;
 	build_mmap_rb(mm);
 
-fail_nomem:
+out:
 	flush_tlb_mm(current->mm);
 	return retval;
+fail_nomem:
+	vm_unacct_memory(charge);
+	goto out;
 }
 
 spinlock_t mmlist_lock __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
@@ -597,22 +608,20 @@
 }
 
 /*
- *  Ok, this is the main fork-routine. It copies the system process
- * information (task[nr]) and sets up the necessary registers. It also
- * copies the data segment in its entirety.  The "stack_start" and
- * "stack_top" arguments are simply passed along to the platform
- * specific copy_thread() routine.  Most platforms ignore stack_top.
- * For an example that's using stack_top, see
- * arch/ia64/kernel/process.c.
+ * This creates a new process as a copy of the old one,
+ * but does not actually start it yet.
+ *
+ * It copies the registers, and all the appropriate
+ * parts of the process environment (as per the clone
+ * flags). The actual kick-off is left to the caller.
  */
-struct task_struct *do_fork(unsigned long clone_flags,
+static struct task_struct *copy_process(unsigned long clone_flags,
 			    unsigned long stack_start,
 			    struct pt_regs *regs,
 			    unsigned long stack_size)
 {
 	int retval;
 	struct task_struct *p = NULL;
-	struct completion vfork;
 
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
 		return ERR_PTR(-EINVAL);
@@ -669,10 +678,6 @@
 	INIT_LIST_HEAD(&p->sibling);
 	init_waitqueue_head(&p->wait_chldexit);
 	p->vfork_done = NULL;
-	if (clone_flags & CLONE_VFORK) {
-		p->vfork_done = &vfork;
-		init_completion(&vfork);
-	}
 	spin_lock_init(&p->alloc_lock);
 	spin_lock_init(&p->switch_lock);
 
@@ -792,20 +797,6 @@
 	hash_pid(p);
 	nr_threads++;
 	write_unlock_irq(&tasklist_lock);
-
-	if (p->ptrace & PT_PTRACED)
-		send_sig(SIGSTOP, p, 1);
-
-	wake_up_forked_process(p);		/* do this last */
-	++total_forks;
-	if (clone_flags & CLONE_VFORK)
-		wait_for_completion(&vfork);
-	else
-		/*
-		 * Let the child process run first, to avoid most of the
-		 * COW overhead when the child exec()s afterwards.
-		 */
-		set_need_resched();
 	retval = 0;
 
 fork_out:
@@ -837,6 +828,45 @@
 bad_fork_free:
 	put_task_struct(p);
 	goto fork_out;
+}
+
+/*
+ *  Ok, this is the main fork-routine.
+ *
+ * It copies the process, and if successful kick-starts
+ * it and waits for it to finish using the VM if required.
+ */
+struct task_struct *do_fork(unsigned long clone_flags,
+			    unsigned long stack_start,
+			    struct pt_regs *regs,
+			    unsigned long stack_size)
+{
+	struct task_struct *p;
+
+	p = copy_process(clone_flags, stack_start, regs, stack_size);
+	if (!IS_ERR(p)) {
+		struct completion vfork;
+
+		if (clone_flags & CLONE_VFORK) {
+			p->vfork_done = &vfork;
+			init_completion(&vfork);
+		}
+
+		if (p->ptrace & PT_PTRACED)
+			send_sig(SIGSTOP, p, 1);
+
+		wake_up_forked_process(p);		/* do this last */
+		++total_forks;
+		if (clone_flags & CLONE_VFORK)
+			wait_for_completion(&vfork);
+		else
+			/*
+			 * Let the child process run first, to avoid most of the
+			 * COW overhead when the child exec()s afterwards.
+			 */
+			set_need_resched();
+	}
+	return p;
 }
 
 /* SLAB cache for signal_struct structures (tsk->sig) */
diff -Nru a/kernel/futex.c b/kernel/futex.c
--- a/kernel/futex.c	Thu Aug  1 14:17:39 2002
+++ b/kernel/futex.c	Thu Aug  1 14:17:39 2002
@@ -245,8 +245,8 @@
 }
 
 static struct file_operations futex_fops = {
-	release:	futex_close,
-	poll:		futex_poll,
+	.release	= futex_close,
+	.poll		= futex_poll,
 };
 
 /* Signal allows caller to avoid the race which would occur if they
@@ -357,8 +357,8 @@
 }
 
 static struct file_system_type futex_fs_type = {
-	name:		"futexfs",
-	get_sb:		futexfs_get_sb,
+	.name		= "futexfs",
+	.get_sb		= futexfs_get_sb,
 };
 
 static int __init init(void)
diff -Nru a/kernel/kmod.c b/kernel/kmod.c
--- a/kernel/kmod.c	Thu Aug  1 14:17:39 2002
+++ b/kernel/kmod.c	Thu Aug  1 14:17:39 2002
@@ -346,15 +346,15 @@
 {
 	DECLARE_COMPLETION(work);
 	struct subprocess_info sub_info = {
-		complete:	&work,
-		path:		path,
-		argv:		argv,
-		envp:		envp,
-		retval:		0,
+		.complete	= &work,
+		.path		= path,
+		.argv		= argv,
+		.envp		= envp,
+		.retval		= 0,
 	};
 	struct tq_struct tqs = {
-		routine:	__call_usermodehelper,
-		data:		&sub_info,
+		.routine	= __call_usermodehelper,
+		.data		= &sub_info,
 	};
 
 	if (path[0] == '\0')
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Thu Aug  1 14:17:36 2002
+++ b/kernel/ksyms.c	Thu Aug  1 14:17:36 2002
@@ -105,6 +105,7 @@
 EXPORT_SYMBOL(kmem_cache_shrink);
 EXPORT_SYMBOL(kmem_cache_alloc);
 EXPORT_SYMBOL(kmem_cache_free);
+EXPORT_SYMBOL(kmem_cache_size);
 EXPORT_SYMBOL(kmalloc);
 EXPORT_SYMBOL(kfree);
 EXPORT_SYMBOL(vfree);
@@ -218,6 +219,7 @@
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(generic_block_bmap);
 EXPORT_SYMBOL(generic_file_read);
+EXPORT_SYMBOL(generic_file_sendfile);
 EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
 EXPORT_SYMBOL(generic_file_mmap);
@@ -340,6 +342,7 @@
 EXPORT_SYMBOL(read_dev_sector);
 EXPORT_SYMBOL(init_buffer);
 EXPORT_SYMBOL(wipe_partitions);
+EXPORT_SYMBOL(generic_file_direct_IO);
 
 /* tty routines */
 EXPORT_SYMBOL(tty_hangup);
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	Thu Aug  1 14:17:36 2002
+++ b/kernel/module.c	Thu Aug  1 14:17:36 2002
@@ -44,15 +44,15 @@
 
 struct module kernel_module =
 {
-	size_of_struct:		sizeof(struct module),
-	name: 			"",
-	uc:	 		{ATOMIC_INIT(1)},
-	flags:			MOD_RUNNING,
-	syms:			__start___ksymtab,
-	ex_table_start:		__start___ex_table,
-	ex_table_end:		__stop___ex_table,
-	kallsyms_start:		__start___kallsyms,
-	kallsyms_end:		__stop___kallsyms,
+	.size_of_struct		= sizeof(struct module),
+	.name 			= "",
+	.uc	 		= {ATOMIC_INIT(1)},
+	.flags			= MOD_RUNNING,
+	.syms			= __start___ksymtab,
+	.ex_table_start		= __start___ex_table,
+	.ex_table_end		= __stop___ex_table,
+	.kallsyms_start		= __start___kallsyms,
+	.kallsyms_end		= __stop___kallsyms,
 };
 
 struct module *module_list = &kernel_module;
@@ -1132,10 +1132,10 @@
 	return 0;
 }
 struct seq_operations modules_op = {
-	start:	m_start,
-	next:	m_next,
-	stop:	m_stop,
-	show:	m_show
+	.start	= m_start,
+	.next	= m_next,
+	.stop	= m_stop,
+	.show	= m_show
 };
 
 /*
@@ -1214,10 +1214,10 @@
 }
 
 struct seq_operations ksyms_op = {
-	start:	s_start,
-	next:	s_next,
-	stop:	s_stop,
-	show:	s_show
+	.start	= s_start,
+	.next	= s_next,
+	.stop	= s_stop,
+	.show	= s_show
 };
 
 #else		/* CONFIG_MODULES */
diff -Nru a/kernel/platform.c b/kernel/platform.c
--- a/kernel/platform.c	Thu Aug  1 14:17:40 2002
+++ b/kernel/platform.c	Thu Aug  1 14:17:40 2002
@@ -23,13 +23,13 @@
 }
 
 static struct platform_t default_platform = {
-	name:		"Default Platform",
-	suspend_states:	0,
-	reboot:		default_reboot,
-	halt:		default_halt,
-	power_off:	default_halt,
-	suspend:	default_suspend,
-	idle:		default_idle,
+	.name		= "Default Platform",
+	.suspend_states	= 0,
+	.reboot		= default_reboot,
+	.halt		= default_halt,
+	.power_off	= default_halt,
+	.suspend	= default_suspend,
+	.idle		= default_idle,
 };
 
 struct platform_t * platform = &default_platform;
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Thu Aug  1 14:17:41 2002
+++ b/kernel/ptrace.c	Thu Aug  1 14:17:41 2002
@@ -11,6 +11,7 @@
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
+#include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
 #include <asm/pgtable.h>
@@ -156,7 +157,7 @@
 			flush_page_to_ram(page);
 		}
 		kunmap(page);
-		put_page(page);
+		page_cache_release(page);
 		len -= bytes;
 		buf += bytes;
 		addr += bytes;
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	Thu Aug  1 14:17:39 2002
+++ b/kernel/sched.c	Thu Aug  1 14:17:39 2002
@@ -107,9 +107,9 @@
  * BASE_TIMESLICE scales user-nice values [ -20 ... 19 ]
  * to time slice values.
  *
- * The higher a process's priority, the bigger timeslices
+ * The higher a thread's priority, the bigger timeslices
  * it gets during one round of execution. But even the lowest
- * priority process gets MIN_TIMESLICE worth of execution time.
+ * priority thread gets MIN_TIMESLICE worth of execution time.
  *
  * task_timeslice() is the interface that is used by the scheduler.
  */
@@ -140,7 +140,7 @@
  * This is the main, per-CPU runqueue data structure.
  *
  * Locking rule: those places that want to lock multiple runqueues
- * (such as the load balancing or the process migration code), lock
+ * (such as the load balancing or the thread migration code), lock
  * acquire operations must be ordered by ascending &runqueue.
  */
 struct runqueue {
@@ -237,21 +237,24 @@
 	p->array = array;
 }
 
+/*
+ * effective_prio - return the priority that is based on the static
+ * priority but is modified by bonuses/penalties.
+ *
+ * We scale the actual sleep average [0 .... MAX_SLEEP_AVG]
+ * into the -5 ... 0 ... +5 bonus/penalty range.
+ *
+ * We use 25% of the full 0...39 priority range so that:
+ *
+ * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
+ * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
+ *
+ * Both properties are important to certain workloads.
+ */
 static inline int effective_prio(task_t *p)
 {
 	int bonus, prio;
 
-	/*
-	 * Here we scale the actual sleep average [0 .... MAX_SLEEP_AVG]
-	 * into the -5 ... 0 ... +5 bonus/penalty range.
-	 *
-	 * We use 25% of the full 0...39 priority range so that:
-	 *
-	 * 1) nice +19 interactive tasks do not preempt nice 0 CPU hogs.
-	 * 2) nice -20 CPU hogs do not get preempted by nice 0 tasks.
-	 *
-	 * Both properties are important to certain workloads.
-	 */
 	bonus = MAX_USER_PRIO*PRIO_BONUS_RATIO*p->sleep_avg/MAX_SLEEP_AVG/100 -
 			MAX_USER_PRIO*PRIO_BONUS_RATIO/100/2;
 
@@ -263,6 +266,12 @@
 	return prio;
 }
 
+/*
+ * activate_task - move a task to the runqueue.
+
+ * Also update all the scheduling statistics stuff. (sleep average
+ * calculation, priority modifiers, etc.)
+ */
 static inline void activate_task(task_t *p, runqueue_t *rq)
 {
 	unsigned long sleep_time = jiffies - p->sleep_timestamp;
@@ -285,6 +294,9 @@
 	rq->nr_running++;
 }
 
+/*
+ * deactivate_task - remove a task from the runqueue.
+ */
 static inline void deactivate_task(struct task_struct *p, runqueue_t *rq)
 {
 	rq->nr_running--;
@@ -294,6 +306,13 @@
 	p->array = NULL;
 }
 
+/*
+ * resched_task - mark a task 'to be rescheduled now'.
+ *
+ * On UP this means the setting of the need_resched flag, on SMP it
+ * might also involve a cross-CPU call to trigger the scheduler on
+ * the target CPU.
+ */
 static inline void resched_task(task_t *p)
 {
 #ifdef CONFIG_SMP
@@ -316,8 +335,10 @@
 #ifdef CONFIG_SMP
 
 /*
- * Wait for a process to unschedule. This is used by the exit() and
- * ptrace() code.
+ * wait_task_inactive - wait for a thread to unschedule.
+ *
+ * The caller must ensure that the task *will* unschedule sometime soon,
+ * else this function might spin for a *long* time.
  */
 void wait_task_inactive(task_t * p)
 {
@@ -349,9 +370,10 @@
 #endif
 
 /*
- * Kick the remote CPU if the task is running currently,
- * this code is used by the signal code to signal tasks
- * which are in user-mode as quickly as possible.
+ * kick_if_running - kick the remote CPU if the task is running currently.
+ *
+ * This code is used by the signal code to signal tasks
+ * which are in user-mode, as quickly as possible.
  *
  * (Note that we do this lockless - if the task does anything
  * while the message is in flight then it will notice the
@@ -363,13 +385,16 @@
 		resched_task(p);
 }
 
-/*
- * Wake up a process. Put it on the run-queue if it's not
- * already there.  The "current" process is always on the
- * run-queue (except when the actual re-schedule is in
- * progress), and as such you're allowed to do the simpler
- * "current->state = TASK_RUNNING" to mark yourself runnable
- * without the overhead of this.
+/***
+ * try_to_wake_up - wake up a thread
+ * @p: the to-be-woken-up thread
+ * @sync: do a synchronous wakeup?
+ *
+ * Put it on the run-queue if it's not already there. The "current"
+ * thread is always on the run-queue (except when the actual
+ * re-schedule is in progress), and as such you're allowed to do
+ * the simpler "current->state = TASK_RUNNING" to mark yourself
+ * runnable without the overhead of this.
  *
  * returns failure only if the task is already active.
  */
@@ -415,6 +440,12 @@
 	return try_to_wake_up(p, 0);
 }
 
+/*
+ * wake_up_forked_process - wake up a freshly forked process.
+ *
+ * This function will do some initial scheduler statistics housekeeping
+ * that must be done for every newly created process.
+ */
 void wake_up_forked_process(task_t * p)
 {
 	runqueue_t *rq = this_rq_lock();
@@ -439,7 +470,7 @@
 /*
  * Potentially available exiting-child timeslices are
  * retrieved here - this way the parent does not get
- * penalized for creating too many processes.
+ * penalized for creating too many threads.
  *
  * (this cannot be used to 'generate' timeslices
  * artificially, because any timeslice recovered here
@@ -463,6 +494,10 @@
 			p->sleep_avg) / (EXIT_WEIGHT + 1);
 }
 
+/**
+ * schedule_tail - first thing a freshly forked thread must call.
+ * @prev: the thread we just switched away from.
+ */
 #if CONFIG_SMP || CONFIG_PREEMPT
 asmlinkage void schedule_tail(task_t *prev)
 {
@@ -470,6 +505,10 @@
 }
 #endif
 
+/*
+ * context_switch - switch to the new MM and the new
+ * thread's register state.
+ */
 static inline task_t * context_switch(task_t *prev, task_t *next)
 {
 	struct mm_struct *mm = next->mm;
@@ -493,6 +532,13 @@
 	return prev;
 }
 
+/*
+ * nr_running, nr_uninterruptible and nr_context_switches:
+ *
+ * externally visible scheduler statistics: current number of runnable
+ * threads, current number of uninterruptible-sleeping threads, total
+ * number of context switches performed since bootup.
+ */
 unsigned long nr_running(void)
 {
 	unsigned long i, sum = 0;
@@ -560,8 +606,10 @@
 #if CONFIG_SMP
 
 /*
- * Lock the busiest runqueue as well, this_rq is locked already.
- * Recalculate nr_running if we have to drop the runqueue lock.
+ * double_lock_balance - lock the busiest runqueue
+ *
+ * this_rq is locked already. Recalculate nr_running if we have to
+ * drop the runqueue lock.
  */
 static inline unsigned int double_lock_balance(runqueue_t *this_rq,
 	runqueue_t *busiest, int this_cpu, int idle, unsigned int nr_running)
@@ -582,6 +630,9 @@
 	return nr_running;
 }
 
+/*
+ * find_busiest_queue - find the busiest runqueue.
+ */
 static inline runqueue_t *find_busiest_queue(runqueue_t *this_rq, int this_cpu, int idle, int *imbalance)
 {
 	int nr_running, load, max_load, i;
@@ -658,7 +709,7 @@
 }
 
 /*
- * Move a task from a remote runqueue to the local runqueue.
+ * pull_task - move a task from a remote runqueue to the local runqueue.
  * Both runqueues must be locked.
  */
 static inline void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p, runqueue_t *this_rq, int this_cpu)
@@ -762,8 +813,8 @@
 }
 
 /*
- * One of the idle_cpu_tick() or the busy_cpu_tick() function will
- * gets called every timer tick, on every CPU. Our balancing action
+ * One of the idle_cpu_tick() and busy_cpu_tick() functions will
+ * get called every timer tick, on every CPU. Our balancing action
  * frequency and balancing agressivity depends on whether the CPU is
  * idle or not.
  *
@@ -848,7 +899,7 @@
 	/*
 	 * The task was running during this tick - update the
 	 * time slice counter and the sleep average. Note: we
-	 * do not update a process's priority until it either
+	 * do not update a thread's priority until it either
 	 * goes to sleep or uses up its timeslice. This makes
 	 * it possible for interactive tasks to use up their
 	 * timeslices at their highest priority levels.
@@ -880,7 +931,7 @@
 void scheduling_functions_start_here(void) { }
 
 /*
- * 'schedule()' is the main scheduler function.
+ * schedule() is the main scheduler function.
  */
 asmlinkage void schedule(void)
 {
@@ -1034,6 +1085,12 @@
 	}
 }
 
+/**
+ * __wake_up - wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ */
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
@@ -1056,6 +1113,17 @@
 
 #if CONFIG_SMP
 
+/**
+ * __wake_up - sync- wake up threads blocked on a waitqueue.
+ * @q: the waitqueue
+ * @mode: which threads
+ * @nr_exclusive: how many wake-one or wake-many threads to wake up
+ *
+ * The sync wakeup differs that the waker knows that it will schedule
+ * away soon, so while the target thread will be woken up, it will not
+ * be migrated to another CPU - ie. the two threads are 'synchronized'
+ * with each other. This can prevent needless bouncing between CPUs.
+ */
 void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
@@ -1207,11 +1275,12 @@
 #ifndef __alpha__
 
 /*
- * This has been replaced by sys_setpriority.  Maybe it should be
- * moved into the arch dependent tree for those ports that require
- * it for backward compatibility?
+ * sys_nice - change the priority of the current process.
+ * @increment: priority increment
+ *
+ * sys_setpriority is a more generic, but much slower function that
+ * does similar things.
  */
-
 asmlinkage long sys_nice(int increment)
 {
 	int retval;
@@ -1247,9 +1316,11 @@
 
 #endif
 
-/*
- * This is the priority value as seen by users in /proc
+/**
+ * task_prio - return the priority value of a given task.
+ * @p: the task in question.
  *
+ * This is the priority value as seen by users in /proc.
  * RT tasks are offset by -200. Normal tasks are centered
  * around 0, value goes from -16 to +15.
  */
@@ -1258,21 +1329,36 @@
 	return p->prio - MAX_USER_RT_PRIO;
 }
 
+/**
+ * task_nice - return the nice value of a given task.
+ * @p: the task in question.
+ */
 int task_nice(task_t *p)
 {
 	return TASK_NICE(p);
 }
 
+/**
+ * idle_cpu - is a given cpu idle currently?
+ * @cpu: the processor in question.
+ */
 int idle_cpu(int cpu)
 {
 	return cpu_curr(cpu) == cpu_rq(cpu)->idle;
 }
 
+/**
+ * find_process_by_pid - find a process with a matching PID value.
+ * @pid: the pid in question.
+ */
 static inline task_t *find_process_by_pid(pid_t pid)
 {
 	return pid ? find_task_by_pid(pid) : current;
 }
 
+/*
+ * setscheduler - change the scheduling policy and/or RT priority of a thread.
+ */
 static int setscheduler(pid_t pid, int policy, struct sched_param *param)
 {
 	struct sched_param lp;
@@ -1359,17 +1445,32 @@
 	return retval;
 }
 
+/**
+ * sys_sched_setscheduler - set/change the scheduler policy and RT priority
+ * @pid: the pid in question.
+ * @policy: new policy
+ * @param: structure containing the new RT priority.
+ */
 asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
 				      struct sched_param *param)
 {
 	return setscheduler(pid, policy, param);
 }
 
+/**
+ * sys_sched_setparam - set/change the RT priority of a thread
+ * @pid: the pid in question.
+ * @param: structure containing the new RT priority.
+ */
 asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param *param)
 {
 	return setscheduler(pid, -1, param);
 }
 
+/**
+ * sys_sched_getscheduler - get the policy (scheduling class) of a thread
+ * @pid: the pid in question.
+ */
 asmlinkage long sys_sched_getscheduler(pid_t pid)
 {
 	int retval = -EINVAL;
@@ -1392,6 +1493,11 @@
 	return retval;
 }
 
+/**
+ * sys_sched_getscheduler - get the RT priority of a thread
+ * @pid: the pid in question.
+ * @param: structure containing the RT priority.
+ */
 asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param)
 {
 	struct sched_param lp;
@@ -1516,6 +1622,13 @@
 	return real_len;
 }
 
+/**
+ * sys_sched_yield - yield the current processor to other threads.
+ *
+ * this function yields the current CPU by moving the calling thread
+ * to the expired array. If there are no other threads running on this
+ * CPU then this function will return.
+ */
 asmlinkage long sys_sched_yield(void)
 {
 	runqueue_t *rq = this_rq_lock();
@@ -1553,12 +1666,25 @@
 	schedule();
 }
 
+/**
+ * yield - yield the current processor to other threads.
+ *
+ * this is a shortcut for kernel-space yielding - it marks the
+ * thread runnable and calls sys_sched_yield().
+ */
 void yield(void)
 {
 	set_current_state(TASK_RUNNING);
 	sys_sched_yield();
 }
 
+/**
+ * sys_sched_get_priority_max - return maximum RT priority.
+ * @policy: scheduling class.
+ *
+ * this syscall returns the maximum rt_priority that can be used
+ * by a given scheduling class.
+ */
 asmlinkage long sys_sched_get_priority_max(int policy)
 {
 	int ret = -EINVAL;
@@ -1575,6 +1701,13 @@
 	return ret;
 }
 
+/**
+ * sys_sched_get_priority_mix - return minimum RT priority.
+ * @policy: scheduling class.
+ *
+ * this syscall returns the minimum rt_priority that can be used
+ * by a given scheduling class.
+ */
 asmlinkage long sys_sched_get_priority_min(int policy)
 {
 	int ret = -EINVAL;
@@ -1590,6 +1723,14 @@
 	return ret;
 }
 
+/**
+ * sys_sched_rr_get_interval - return the default timeslice of a process.
+ * @pid: pid of the process.
+ * @interval: userspace pointer to the timeslice value.
+ *
+ * this syscall writes the default timeslice value of a given process
+ * into the user-space timespec buffer. A value of '0' means infinity.
+ */
 asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval)
 {
 	int retval = -EINVAL;
@@ -1765,7 +1906,7 @@
 } migration_req_t;
 
 /*
- * Change a given task's CPU affinity. Migrate the process to a
+ * Change a given task's CPU affinity. Migrate the thread to a
  * proper CPU and schedule it away if the CPU it's executing on
  * is removed from the allowed bitmask.
  *
@@ -1790,7 +1931,7 @@
 	p->cpus_allowed = new_mask;
 	/*
 	 * Can the task run on the task's current CPU? If not then
-	 * migrate the process off to a proper CPU.
+	 * migrate the thread off to a proper CPU.
 	 */
 	if (new_mask & (1UL << task_cpu(p))) {
 		task_rq_unlock(rq, &flags);
@@ -1816,10 +1957,14 @@
 	preempt_enable();
 }
 
-static int migration_thread(void * bind_cpu)
+/*
+ * migration_thread - this is a highprio system thread that performs
+ * thread migration by 'pulling' threads into the target runqueue.
+ */
+static int migration_thread(void * data)
 {
-	int cpu = (int) (long) bind_cpu;
-	struct sched_param param = { sched_priority: MAX_RT_PRIO-1 };
+	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
+	int cpu = (long) data;
 	runqueue_t *rq;
 	int ret;
 
@@ -1828,6 +1973,14 @@
 	set_fs(KERNEL_DS);
 
 	set_cpus_allowed(current, 1UL << cpu);
+
+	/*
+	 * Migration can happen without a migration thread on the
+	 * target CPU because here we remove the thread from the
+	 * runqueue and the helper thread then moves this thread
+	 * to the target CPU - we'll wake up there.
+	 */
+	if (smp_processor_id() != cpu)
 	printk("migration_task %d on cpu=%d\n", cpu, smp_processor_id());
 	ret = setscheduler(0, SCHED_FIFO, &param);
 
@@ -1884,6 +2037,10 @@
 	}
 }
 
+/*
+ * migration_call - callback that gets triggered when a CPU is added.
+ * Here we can start up the necessary migration thread for the new CPU.
+ */
 static int migration_call(struct notifier_block *nfb,
 			  unsigned long action,
 			  void *hcpu)
@@ -1894,6 +2051,8 @@
 		       (long)hcpu);
 		kernel_thread(migration_thread, hcpu,
 			      CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
+		while (!cpu_rq((long)hcpu)->migration_thread)
+			yield();
 		break;
 	}
 	return NOTIFY_OK;
@@ -1901,7 +2060,7 @@
 
 static struct notifier_block migration_notifier = { &migration_call, NULL, 0 };
 
-int __init migration_init(void)
+__init int migration_init(void)
 {
 	/* Start one for boot CPU. */
 	migration_call(&migration_notifier, CPU_ONLINE,
@@ -1910,7 +2069,6 @@
 	return 0;
 }
 
-__initcall(migration_init);
 #endif
 
 extern void init_timervecs(void);
@@ -1944,7 +2102,7 @@
 	}
 	/*
 	 * We have to do a little magic to get the first
-	 * process right in SMP mode.
+	 * thread right in SMP mode.
 	 */
 	rq = this_rq();
 	rq->curr = current;
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	Thu Aug  1 14:17:39 2002
+++ b/kernel/softirq.c	Thu Aug  1 14:17:39 2002
@@ -410,11 +410,9 @@
 
 static struct notifier_block cpu_nfb = { &cpu_callback, NULL, 0 };
 
-static __init int spawn_ksoftirqd(void)
+__init int spawn_ksoftirqd(void)
 {
 	cpu_callback(&cpu_nfb, CPU_ONLINE, (void *)smp_processor_id());
 	register_cpu_notifier(&cpu_nfb);
 	return 0;
 }
-
-__initcall(spawn_ksoftirqd);
diff -Nru a/kernel/suspend.c b/kernel/suspend.c
--- a/kernel/suspend.c	Thu Aug  1 14:17:39 2002
+++ b/kernel/suspend.c	Thu Aug  1 14:17:39 2002
@@ -36,7 +36,6 @@
 
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/swapctl.h>
 #include <linux/suspend.h>
 #include <linux/smp_lock.h>
 #include <linux/file.h>
@@ -66,6 +65,7 @@
 #include <linux/swapops.h>
 
 extern void signal_wake_up(struct task_struct *t);
+extern int sys_sync(void);
 
 unsigned char software_suspend_enabled = 0;
 
@@ -815,17 +815,17 @@
 	PRINTK(KERN_WARNING "%sLeaving do_magic_suspend_2...\n", name_suspend);	
 }
 
-/*
- * We try to swap out as much as we can then make a copy of the
- * occupied pages in memory so we can make a copy of kernel state
- * atomically, the I/O needed by saving won't bother us anymore. 
- */
 void do_software_suspend(void)
 {
 	arch_prepare_suspend();
 	if (prepare_suspend_console())
 		printk( "%sCan't allocate a console... proceeding\n", name_suspend);
 	if (!prepare_suspend_processes()) {
+
+		/* At this point, all user processes and "dangerous"
+                   kernel threads are stopped. Free some memory, as we
+                   need half of memory free. */
+
 		free_some_memory();
 		
 		/* No need to invalidate any vfsmnt list -- they will be valid after resume, anyway.
@@ -835,8 +835,19 @@
 		 */
 		PRINTK("Syncing disks before copy\n");
 		do_suspend_sync();
+
+		/* Save state of all device drivers, and stop them. */		   
 		if(drivers_suspend()==0)
-			do_magic(0);			/* This function returns after machine woken up from resume */
+			/* If stopping device drivers worked, we proceed basically into
+			 * suspend_save_image.
+			 *
+			 * do_magic(0) returns after system is resumed.
+			 *
+			 * do_magic() copies all "used" memory to "free" memory, then
+			 * unsuspends all device drivers, and writes memory to disk
+			 * using normal kernel mechanism.
+			 */
+			do_magic(0);
 		PRINTK("Restarting processes...\n");
 		thaw_processes();
 	}
@@ -1004,8 +1015,8 @@
 
 static int bdev_write_page(struct block_device *bdev, long pos, void *buf)
 {
-	struct buffer_head *bh;
 #if 0
+	struct buffer_head *bh;
 	BUG_ON (pos%PAGE_SIZE);
 	bh = __bread(bdev, pos/PAGE_SIZE, PAGE_SIZE);
 	if (!bh || (!bh->b_data)) {
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	Thu Aug  1 14:17:36 2002
+++ b/kernel/sys.c	Thu Aug  1 14:17:36 2002
@@ -391,7 +391,7 @@
 void ctrl_alt_del(void)
 {
 	static struct tq_struct cad_tq = {
-		routine: deferred_cad,
+		.routine = deferred_cad,
 	};
 
 	if (C_A_D)
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Thu Aug  1 14:17:36 2002
+++ b/kernel/sysctl.c	Thu Aug  1 14:17:36 2002
@@ -22,7 +22,6 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/sysctl.h>
-#include <linux/swapctl.h>
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
 #include <linux/utsname.h>
@@ -45,6 +44,7 @@
 extern int panic_timeout;
 extern int C_A_D;
 extern int sysctl_overcommit_memory;
+extern int sysctl_overcommit_ratio;
 extern int max_threads;
 extern atomic_t nr_queued_signals;
 extern int max_queued_signals;
@@ -126,12 +126,12 @@
 static int proc_sys_permission(struct inode *, int);
 
 struct file_operations proc_sys_file_operations = {
-	read:		proc_readsys,
-	write:		proc_writesys,
+	.read		= proc_readsys,
+	.write		= proc_writesys,
 };
 
 static struct inode_operations proc_sys_inode_operations = {
-	permission:	proc_sys_permission,
+	.permission	= proc_sys_permission,
 };
 
 extern struct proc_dir_entry *proc_sys_root;
@@ -268,8 +268,9 @@
 static ctl_table vm_table[] = {
 	{VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
 	 sizeof(sysctl_overcommit_memory), 0644, NULL, &proc_dointvec},
-	{VM_PAGERDAEMON, "kswapd",
-	 &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
+	{VM_OVERCOMMIT_RATIO, "overcommit_ratio",
+	 &sysctl_overcommit_ratio, sizeof(sysctl_overcommit_ratio), 0644,
+	 NULL, &proc_dointvec},
 	{VM_PAGE_CLUSTER, "page-cluster", 
 	 &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
 	{VM_DIRTY_BACKGROUND, "dirty_background_ratio",
diff -Nru a/kernel/user.c b/kernel/user.c
--- a/kernel/user.c	Thu Aug  1 14:17:40 2002
+++ b/kernel/user.c	Thu Aug  1 14:17:40 2002
@@ -28,9 +28,9 @@
 static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;
 
 struct user_struct root_user = {
-	__count:	ATOMIC_INIT(1),
-	processes:	ATOMIC_INIT(1),
-	files:		ATOMIC_INIT(0)
+	.__count	= ATOMIC_INIT(1),
+	.processes	= ATOMIC_INIT(1),
+	.files		= ATOMIC_INIT(0)
 };
 
 /*
diff -Nru a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
--- a/lib/rwsem-spinlock.c	Thu Aug  1 14:17:36 2002
+++ b/lib/rwsem-spinlock.c	Thu Aug  1 14:17:36 2002
@@ -46,8 +46,9 @@
  *   - the 'waiting count' is non-zero
  * - the spinlock must be held by the caller
  * - woken process blocks are discarded from the list after having flags zeroised
+ * - writers are only woken if wakewrite is non-zero
  */
-static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem)
+static inline struct rw_semaphore *__rwsem_do_wake(struct rw_semaphore *sem, int wakewrite)
 {
 	struct rwsem_waiter *waiter;
 	int woken;
@@ -56,7 +57,14 @@
 
 	waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
 
-	/* try to grant a single write lock if there's a writer at the front of the queue
+	if (!wakewrite) {
+		if (waiter->flags & RWSEM_WAITING_FOR_WRITE)
+			goto out;
+		goto dont_wake_writers;
+	}
+
+	/* if we are allowed to wake writers try to grant a single write lock if there's a
+	 * writer at the front of the queue
 	 * - we leave the 'waiting count' incremented to signify potential contention
 	 */
 	if (waiter->flags & RWSEM_WAITING_FOR_WRITE) {
@@ -68,16 +76,19 @@
 	}
 
 	/* grant an infinite number of read locks to the readers at the front of the queue */
+ dont_wake_writers:
 	woken = 0;
-	do {
+	while (waiter->flags&RWSEM_WAITING_FOR_READ) {
+		struct list_head *next = waiter->list.next;
+
 		list_del(&waiter->list);
 		waiter->flags = 0;
 		wake_up_process(waiter->task);
 		woken++;
 		if (list_empty(&sem->wait_list))
 			break;
-		waiter = list_entry(sem->wait_list.next,struct rwsem_waiter,list);
-	} while (waiter->flags&RWSEM_WAITING_FOR_READ);
+		waiter = list_entry(next,struct rwsem_waiter,list);
+	}
 
 	sem->activity += woken;
 
@@ -149,6 +160,28 @@
 }
 
 /*
+ * trylock for reading -- returns 1 if successful, 0 if contention
+ */
+int __down_read_trylock(struct rw_semaphore *sem)
+{
+	int ret = 0;
+	rwsemtrace(sem,"Entering __down_read_trylock");
+
+	spin_lock(&sem->wait_lock);
+
+	if (sem->activity>=0 && list_empty(&sem->wait_list)) {
+		/* granted */
+		sem->activity++;
+		ret = 1;
+	}
+
+	spin_unlock(&sem->wait_lock);
+
+	rwsemtrace(sem,"Leaving __down_read_trylock");
+	return ret;
+}
+
+/*
  * get a write lock on the semaphore
  * - note that we increment the waiting count anyway to indicate an exclusive lock
  */
@@ -195,6 +228,28 @@
 }
 
 /*
+ * trylock for writing -- returns 1 if successful, 0 if contention
+ */
+int __down_write_trylock(struct rw_semaphore *sem)
+{
+	int ret = 0;
+	rwsemtrace(sem,"Entering __down_write_trylock");
+
+	spin_lock(&sem->wait_lock);
+
+	if (sem->activity==0 && list_empty(&sem->wait_list)) {
+		/* granted */
+		sem->activity = -1;
+		ret = 1;
+	}
+
+	spin_unlock(&sem->wait_lock);
+
+	rwsemtrace(sem,"Leaving __down_write_trylock");
+	return ret;
+}
+
+/*
  * release a read lock on the semaphore
  */
 void __up_read(struct rw_semaphore *sem)
@@ -222,18 +277,40 @@
 
 	sem->activity = 0;
 	if (!list_empty(&sem->wait_list))
-		sem = __rwsem_do_wake(sem);
+		sem = __rwsem_do_wake(sem, 1);
 
 	spin_unlock(&sem->wait_lock);
 
 	rwsemtrace(sem,"Leaving __up_write");
 }
 
+/*
+ * downgrade a write lock into a read lock
+ * - just wake up any readers at the front of the queue
+ */
+void __downgrade_write(struct rw_semaphore *sem)
+{
+	rwsemtrace(sem,"Entering __rwsem_downgrade");
+
+	spin_lock(&sem->wait_lock);
+
+	sem->activity = 1;
+	if (!list_empty(&sem->wait_list))
+		sem = __rwsem_do_wake(sem,0);
+
+	spin_unlock(&sem->wait_lock);
+
+	rwsemtrace(sem,"Leaving __rwsem_downgrade");
+}
+
 EXPORT_SYMBOL(init_rwsem);
 EXPORT_SYMBOL(__down_read);
+EXPORT_SYMBOL(__down_read_trylock);
 EXPORT_SYMBOL(__down_write);
+EXPORT_SYMBOL(__down_write_trylock);
 EXPORT_SYMBOL(__up_read);
 EXPORT_SYMBOL(__up_write);
+EXPORT_SYMBOL(__downgrade_write);
 #if RWSEM_DEBUG
 EXPORT_SYMBOL(rwsemtrace);
 #endif
diff -Nru a/lib/rwsem.c b/lib/rwsem.c
--- a/lib/rwsem.c	Thu Aug  1 14:17:36 2002
+++ b/lib/rwsem.c	Thu Aug  1 14:17:36 2002
@@ -236,6 +236,7 @@
 EXPORT_SYMBOL_NOVERS(rwsem_down_read_failed);
 EXPORT_SYMBOL_NOVERS(rwsem_down_write_failed);
 EXPORT_SYMBOL_NOVERS(rwsem_wake);
+EXPORT_SYMBOL_NOVERS(rwsem_downgrade_wake);
 #if RWSEM_DEBUG
 EXPORT_SYMBOL(rwsemtrace);
 #endif
diff -Nru a/mm/bootmem.c b/mm/bootmem.c
--- a/mm/bootmem.c	Thu Aug  1 14:17:39 2002
+++ b/mm/bootmem.c	Thu Aug  1 14:17:39 2002
@@ -12,7 +12,6 @@
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
@@ -49,7 +48,7 @@
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long mapsize = ((end - start)+7)/8;
 
-	pgdat->node_next = pgdat_list;
+	pgdat->pgdat_next = pgdat_list;
 	pgdat_list = pgdat;
 
 	mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
@@ -339,12 +338,11 @@
 	pg_data_t *pgdat = pgdat_list;
 	void *ptr;
 
-	while (pgdat) {
+	for_each_pgdat(pgdat)
 		if ((ptr = __alloc_bootmem_core(pgdat->bdata, size,
 						align, goal)))
 			return(ptr);
-		pgdat = pgdat->node_next;
-	}
+
 	/*
 	 * Whoops, we cannot satisfy the allocation request.
 	 */
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	Thu Aug  1 14:17:40 2002
+++ b/mm/filemap.c	Thu Aug  1 14:17:40 2002
@@ -173,17 +173,16 @@
 }
 
 /*
- * AKPM: the PagePrivate test here seems a bit bogus.  It bypasses the
- * mapping's ->invalidatepage, which may still want to be called.
+ * If truncate can remove the fs-private metadata from the page, it
+ * removes the page from the LRU immediately.  This because some other thread
+ * of control (eg, sendfile) may have a reference to the page.  But dropping
+ * the final reference to an LRU page in interrupt context is illegal - it may
+ * deadlock over pagemap_lru_lock.
  */
 static void truncate_complete_page(struct page *page)
 {
-	/* Drop fs-specific data so the page might become freeable. */
-	if (PagePrivate(page) && !do_invalidatepage(page, 0)) {
-		if (current->flags & PF_INVALIDATE)
-			printk("%s: buffer heads were leaked\n",
-				current->comm);
-	}
+	if (!PagePrivate(page) || do_invalidatepage(page, 0))
+		lru_cache_del(page);
 
 	ClearPageDirty(page);
 	ClearPageUptodate(page);
@@ -1119,127 +1118,23 @@
 	return written;
 }
 
-static ssize_t common_sendfile(int out_fd, int in_fd, loff_t *offset, size_t count, loff_t max)
+ssize_t generic_file_sendfile(struct file *in_file, struct file *out_file,
+			      loff_t *ppos, size_t count)
 {
-	ssize_t retval;
-	struct file * in_file, * out_file;
-	struct inode * in_inode, * out_inode;
-
-	/*
-	 * Get input file, and verify that it is ok..
-	 */
-	retval = -EBADF;
-	in_file = fget(in_fd);
-	if (!in_file)
-		goto out;
-	if (!(in_file->f_mode & FMODE_READ))
-		goto fput_in;
-	retval = -EINVAL;
-	in_inode = in_file->f_dentry->d_inode;
-	if (!in_inode)
-		goto fput_in;
-	if (!in_inode->i_mapping->a_ops->readpage)
-		goto fput_in;
-	retval = locks_verify_area(FLOCK_VERIFY_READ, in_inode, in_file, in_file->f_pos, count);
-	if (retval)
-		goto fput_in;
-
-	retval = security_ops->file_permission (in_file, MAY_READ);
-	if (retval)
-		goto fput_in;
-
-	/*
-	 * Get output file, and verify that it is ok..
-	 */
-	retval = -EBADF;
-	out_file = fget(out_fd);
-	if (!out_file)
-		goto fput_in;
-	if (!(out_file->f_mode & FMODE_WRITE))
-		goto fput_out;
-	retval = -EINVAL;
-	if (!out_file->f_op || !out_file->f_op->sendpage)
-		goto fput_out;
-	out_inode = out_file->f_dentry->d_inode;
-	retval = locks_verify_area(FLOCK_VERIFY_WRITE, out_inode, out_file, out_file->f_pos, count);
-	if (retval)
-		goto fput_out;
-
-	retval = security_ops->file_permission (out_file, MAY_WRITE);
-	if (retval)
-		goto fput_out;
-
-	retval = 0;
-	if (count) {
-		read_descriptor_t desc;
-		loff_t pos;
-
-		if (!offset)
-			offset = &in_file->f_pos;
+	read_descriptor_t desc;
 
-		pos = *offset;
-		retval = -EINVAL;
-		if (unlikely(pos < 0))
-			goto fput_out;
-		if (unlikely(pos + count > max)) {
-			retval = -EOVERFLOW;
-			if (pos >= max)
-				goto fput_out;
-			count = max - pos;
-		}
-
-		desc.written = 0;
-		desc.count = count;
-		desc.buf = (char *) out_file;
-		desc.error = 0;
-		do_generic_file_read(in_file, offset, &desc, file_send_actor);
-
-		retval = desc.written;
-		if (!retval)
-			retval = desc.error;
-		pos = *offset;
-		if (pos > max)
-			retval = -EOVERFLOW;
-	}
-
-fput_out:
-	fput(out_file);
-fput_in:
-	fput(in_file);
-out:
-	return retval;
-}
+	if (!count)
+		return 0;
 
-asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
-{
-	loff_t pos, *ppos = NULL;
-	ssize_t ret;
-	if (offset) {
-		off_t off;
-		if (unlikely(get_user(off, offset)))
-			return -EFAULT;
-		pos = off;
-		ppos = &pos;
-	}
-	ret = common_sendfile(out_fd, in_fd, ppos, count, MAX_NON_LFS);
-	if (offset && put_user(pos, offset))
-		ret = -EFAULT;
-	return ret;
-}
-
-asmlinkage ssize_t sys_sendfile64(int out_fd, int in_fd, loff_t *offset, size_t count)
-{
-	loff_t pos, *ppos = NULL;
-	ssize_t ret;
-	if (offset) {
-		if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
-			return -EFAULT;
-		ppos = &pos;
-	}
-	ret = common_sendfile(out_fd, in_fd, ppos, count, MAX_LFS_FILESIZE);
-	if (offset && put_user(pos, offset))
-		ret = -EFAULT;
-	return ret;
+	desc.written = 0;
+	desc.count = count;
+	desc.buf = (char *)out_file;
+	desc.error = 0;
+
+	do_generic_file_read(in_file, ppos, &desc, file_send_actor);
+	if (desc.written)
+		return desc.written;
+	return desc.error;
 }
 
 static ssize_t
@@ -1451,7 +1346,7 @@
 }
 
 static struct vm_operations_struct generic_file_vm_ops = {
-	nopage:		filemap_nopage,
+	.nopage		= filemap_nopage,
 };
 
 /* This is used for a general mmap of a disk file */
@@ -2056,8 +1951,6 @@
 				mark_inode_dirty(inode);
 			}
 			*ppos = end;
-			if (mapping->nrpages)
-				invalidate_inode_pages2(mapping);
 		}
 		/*
 		 * Sync the fs metadata but not the minor inode changes and
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	Thu Aug  1 14:17:40 2002
+++ b/mm/memory.c	Thu Aug  1 14:17:40 2002
@@ -41,7 +41,6 @@
 #include <linux/mman.h>
 #include <linux/swap.h>
 #include <linux/smp_lock.h>
-#include <linux/swapctl.h>
 #include <linux/iobuf.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
@@ -863,18 +862,19 @@
 static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
 	unsigned long phys_addr, pgprot_t prot)
 {
-	unsigned long end;
+	unsigned long base, end;
 
+	base = address & PGDIR_MASK;
 	address &= ~PGDIR_MASK;
 	end = address + size;
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	phys_addr -= address;
 	do {
-		pte_t * pte = pte_alloc_map(mm, pmd, address);
+		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
 		if (!pte)
 			return -ENOMEM;
-		remap_pte_range(pte, address, end - address, address + phys_addr, prot);
+		remap_pte_range(pte, base + address, end - address, address + phys_addr, prot);
 		pte_unmap(pte);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
@@ -1096,23 +1096,20 @@
 
 do_expand:
 	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
-	if (limit != RLIM_INFINITY) {
-		if (inode->i_size >= limit) {
-			send_sig(SIGXFSZ, current, 0);
-			goto out;
-		}
-		if (offset > limit) {
-			send_sig(SIGXFSZ, current, 0);
-			offset = limit;
-		}
-	}
+	if (limit != RLIM_INFINITY && offset > limit)
+		goto out_sig;
+	if (offset > inode->i_sb->s_maxbytes)
+		goto out;
 	inode->i_size = offset;
 
 out_truncate:
 	if (inode->i_op && inode->i_op->truncate)
 		inode->i_op->truncate(inode);
-out:
 	return 0;
+out_sig:
+	send_sig(SIGXFSZ, current, 0);
+out:
+	return -EFBIG;
 }
 
 /* 
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Thu Aug  1 14:17:36 2002
+++ b/mm/mmap.c	Thu Aug  1 14:17:36 2002
@@ -1,14 +1,16 @@
 /*
- *	linux/mm/mmap.c
+ * mm/mmap.c
  *
  * Written by obz.
+ *
+ * Address space accounting code	<alan@redhat.com>
  */
+
 #include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/file.h>
@@ -49,52 +51,84 @@
 	__S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
 };
 
-int sysctl_overcommit_memory;
+int sysctl_overcommit_memory = 0;	/* default is heuristic overcommit */
+int sysctl_overcommit_ratio = 50;	/* default is 50% */
+atomic_t vm_committed_space = ATOMIC_INIT(0);
+
+inline void vm_unacct_memory(long pages)
+{	
+	atomic_sub(pages, &vm_committed_space);
+}
 
-/* Check that a process has enough memory to allocate a
- * new virtual mapping.
+/*
+ * Check that a process has enough memory to allocate a new virtual
+ * mapping. 1 means there is enough memory for the allocation to
+ * succeed and 0 implies there is not.
+ *
+ * We currently support three overcommit policies, which are set via the
+ * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-acounting
+ *
+ * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
+ * Additional code 2002 Jul 20 by Robert Love.
  */
 int vm_enough_memory(long pages)
 {
-	/* Stupid algorithm to decide if we have enough memory: while
-	 * simple, it hopefully works in most obvious cases.. Easy to
-	 * fool it, but this should catch most mistakes.
-	 */
-	/* 23/11/98 NJC: Somewhat less stupid version of algorithm,
-	 * which tries to do "TheRightThing".  Instead of using half of
-	 * (buffers+cache), use the minimum values.  Allow an extra 2%
-	 * of num_physpages for safety margin.
-	 */
+	unsigned long free, allowed;
+	struct sysinfo i;
 
-	unsigned long free;
-	
-        /* Sometimes we want to use more memory than we have. */
-	if (sysctl_overcommit_memory)
-	    return 1;
-
-	/* The page cache contains buffer pages these days.. */
-	free = get_page_cache_size();
-	free += nr_free_pages();
-	free += nr_swap_pages;
+	atomic_add(pages, &vm_committed_space);
 
-	/*
-	 * This double-counts: the nrpages are both in the page-cache
-	 * and in the swapper space. At the same time, this compensates
-	 * for the swap-space over-allocation (ie "nr_swap_pages" being
-	 * too small.
+        /*
+	 * Sometimes we want to use more memory than we have
 	 */
-	free += swapper_space.nrpages;
+	if (sysctl_overcommit_memory == 1)
+		return 1;
+
+	if (sysctl_overcommit_memory == 0) {
+		free = get_page_cache_size();
+		free += nr_free_pages();
+		free += nr_swap_pages;
+
+		/*
+		 * This double-counts: the nrpages are both in the
+		 * page-cache and in the swapper space. At the same time,
+		 * this compensates for the swap-space over-allocation
+		 * (ie "nr_swap_pages" being too small).
+		 */
+		free += swapper_space.nrpages;
+
+		/*
+		 * The code below doesn't account for free space in the
+		 * inode and dentry slab cache, slab cache fragmentation,
+		 * inodes and dentries which will become freeable under
+		 * VM load, etc. Lets just hope all these (complex)
+		 * factors balance out...
+		 */
+		free += (dentry_stat.nr_unused * sizeof(struct dentry)) >>
+			PAGE_SHIFT;
+		free += (inodes_stat.nr_unused * sizeof(struct inode)) >>
+			PAGE_SHIFT;
+
+		if (free > pages)
+			return 1;
+		vm_unacct_memory(pages);
+		return 0;
+	}
 
 	/*
-	 * The code below doesn't account for free space in the inode
-	 * and dentry slab cache, slab cache fragmentation, inodes and
-	 * dentries which will become freeable under VM load, etc.
-	 * Lets just hope all these (complex) factors balance out...
+	 * FIXME: need to add arch hooks to get the bits we need
+	 * without this higher overhead crap
 	 */
-	free += (dentry_stat.nr_unused * sizeof(struct dentry)) >> PAGE_SHIFT;
-	free += (inodes_stat.nr_unused * sizeof(struct inode)) >> PAGE_SHIFT;
+	si_meminfo(&i);
+	allowed = i.totalram * sysctl_overcommit_ratio / 100;
+	allowed += total_swap_pages;
+
+	if (atomic_read(&vm_committed_space) < allowed)
+		return 1;
+
+	vm_unacct_memory(pages);
 
-	return free > pages;
+	return 0;
 }
 
 /* Remove one vm structure from the inode's i_mapping address space. */
@@ -177,10 +211,6 @@
 	if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
 		goto out;
 
-	/* Check if we have enough memory.. */
-	if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
-		goto out;
-
 	/* Ok, looks good - let it rip. */
 	if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
 		goto out;
@@ -386,8 +416,9 @@
 	return 0;
 }
 
-unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags, unsigned long pgoff)
+unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
+			unsigned long len, unsigned long prot,
+			unsigned long flags, unsigned long pgoff)
 {
 	struct mm_struct * mm = current->mm;
 	struct vm_area_struct * vma, * prev;
@@ -395,6 +426,7 @@
 	int correct_wcount = 0;
 	int error;
 	rb_node_t ** rb_link, * rb_parent;
+	unsigned long charged = 0;
 
 	if (file && (!file->f_op || !file->f_op->mmap))
 		return -ENODEV;
@@ -495,11 +527,18 @@
 	    > current->rlim[RLIMIT_AS].rlim_cur)
 		return -ENOMEM;
 
-	/* Private writable mapping? Check memory availability.. */
-	if ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE &&
-	    !(flags & MAP_NORESERVE)				 &&
-	    !vm_enough_memory(len >> PAGE_SHIFT))
-		return -ENOMEM;
+	if (!(flags & MAP_NORESERVE) || sysctl_overcommit_memory > 1) {
+		if (vm_flags & VM_SHARED) {
+			/* Check memory availability in shmem_file_setup? */
+			vm_flags |= VM_ACCOUNT;
+		} else if (vm_flags & VM_WRITE) {
+			/* Private writable mapping: check memory availability */
+			charged = len >> PAGE_SHIFT;
+			if (!vm_enough_memory(charged))
+				return -ENOMEM;
+			vm_flags |= VM_ACCOUNT;
+		}
+	}
 
 	/* Can we just expand an old anonymous mapping? */
 	if (!file && !(vm_flags & VM_SHARED) && rb_parent)
@@ -511,8 +550,9 @@
 	 * not unmapped, but the maps are removed from the list.
 	 */
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	error = -ENOMEM;
 	if (!vma)
-		return -ENOMEM;
+		goto unacct_error;
 
 	vma->vm_mm = mm;
 	vma->vm_start = addr;
@@ -540,12 +580,20 @@
 		error = file->f_op->mmap(file, vma);
 		if (error)
 			goto unmap_and_free_vma;
-	} else if (flags & MAP_SHARED) {
+	} else if (vm_flags & VM_SHARED) {
 		error = shmem_zero_setup(vma);
 		if (error)
 			goto free_vma;
 	}
 
+	/* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
+	 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
+	 * that memory reservation must be checked; but that reservation
+	 * belongs to shared memory object, not to vma: so now clear it.
+	 */
+	if ((vm_flags & (VM_SHARED|VM_ACCOUNT)) == (VM_SHARED|VM_ACCOUNT))
+		vma->vm_flags &= ~VM_ACCOUNT;
+
 	/* Can addr have changed??
 	 *
 	 * Answer: Yes, several device drivers can do it in their
@@ -575,6 +623,9 @@
 	zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start);
 free_vma:
 	kmem_cache_free(vm_area_cachep, vma);
+unacct_error:
+	if (charged)
+		vm_unacct_memory(charged);
 	return error;
 }
 
@@ -704,6 +755,45 @@
 	return prev ? prev->vm_next : vma;
 }
 
+/*
+ * vma is the first one with  address < vma->vm_end,
+ * and even address < vma->vm_start. Have to extend vma.
+ */
+int expand_stack(struct vm_area_struct * vma, unsigned long address)
+{
+	unsigned long grow;
+
+	/*
+	 * vma->vm_start/vm_end cannot change under us because the caller
+	 * is required to hold the mmap_sem in write mode. We need to get
+	 * the spinlock only before relocating the vma range ourself.
+	 */
+	address &= PAGE_MASK;
+ 	spin_lock(&vma->vm_mm->page_table_lock);
+	grow = (vma->vm_start - address) >> PAGE_SHIFT;
+
+	/* Overcommit.. */
+	if(!vm_enough_memory(grow)) {
+		spin_unlock(&vma->vm_mm->page_table_lock);
+		return -ENOMEM;
+	}
+	
+	if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
+			((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+			current->rlim[RLIMIT_AS].rlim_cur) {
+		spin_unlock(&vma->vm_mm->page_table_lock);
+		vm_unacct_memory(grow);
+		return -ENOMEM;
+	}
+	vma->vm_start = address;
+	vma->vm_pgoff -= grow;
+	vma->vm_mm->total_vm += grow;
+	if (vma->vm_flags & VM_LOCKED)
+		vma->vm_mm->locked_vm += grow;
+	spin_unlock(&vma->vm_mm->page_table_lock);
+	return 0;
+}
+
 #ifdef ARCH_STACK_GROWSUP
 struct vm_area_struct * find_extend_vma(struct mm_struct * mm, unsigned long addr)
 {
@@ -829,7 +919,6 @@
 	kmem_cache_free(vm_area_cachep, area);
 }
 
-
 /*
  * Update the VMA and inode share lists.
  *
@@ -863,12 +952,17 @@
 	tlb = tlb_gather_mmu(mm, 0);
 
 	do {
-		unsigned long from, to;
+		unsigned long from, to, len;
 
 		from = start < mpnt->vm_start ? mpnt->vm_start : start;
 		to = end > mpnt->vm_end ? mpnt->vm_end : end;
 
 		unmap_page_range(tlb, mpnt, from, to);
+
+		if (mpnt->vm_flags & VM_ACCOUNT) {
+			len = to - from;
+			vm_unacct_memory(len >> PAGE_SHIFT);
+		}
 	} while ((mpnt = mpnt->vm_next) != NULL);
 
 	free_pgtables(tlb, prev, start, end);
@@ -1058,7 +1152,7 @@
 	if (!vm_enough_memory(len >> PAGE_SHIFT))
 		return -ENOMEM;
 
-	flags = VM_DATA_DEFAULT_FLAGS | mm->def_flags;
+	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
 
 	/* Can we just expand an old anonymous mapping? */
 	if (rb_parent && vma_merge(mm, prev, rb_parent, addr, addr + len, flags))
@@ -1068,8 +1162,10 @@
 	 * create a vma struct for an anonymous mapping
 	 */
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
-	if (!vma)
+	if (!vma) {
+		vm_unacct_memory(len >> PAGE_SHIFT);
 		return -ENOMEM;
+	}
 
 	vma->vm_mm = mm;
 	vma->vm_start = addr;
@@ -1124,6 +1220,13 @@
 	while (mpnt) {
 		unsigned long start = mpnt->vm_start;
 		unsigned long end = mpnt->vm_end;
+
+		/*
+		 * If the VMA has been charged for, account for its
+		 * removal
+		 */
+		if (mpnt->vm_flags & VM_ACCOUNT)
+			vm_unacct_memory((end - start) >> PAGE_SHIFT);
 
 		mm->map_count--;
 		unmap_page_range(tlb, mpnt, start, end);
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	Thu Aug  1 14:17:40 2002
+++ b/mm/mprotect.c	Thu Aug  1 14:17:40 2002
@@ -1,7 +1,10 @@
 /*
- *	linux/mm/mprotect.c
+ *  mm/mprotect.c
  *
  *  (C) Copyright 1994 Linus Torvalds
+ *
+ *  Address space accounting code	<alan@redhat.com>
+ *  (C) Copyright 2002 Red Hat Inc, All Rights Reserved
  */
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -248,11 +251,28 @@
 {
 	pgprot_t newprot;
 	int error;
+	unsigned long charged = 0;
 
 	if (newflags == vma->vm_flags) {
 		*pprev = vma;
 		return 0;
 	}
+
+	/*
+	 * If we make a private mapping writable we increase our commit;
+	 * but (without finer accounting) cannot reduce our commit if we
+	 * make it unwritable again.
+	 *
+	 * FIXME? We haven't defined a VM_NORESERVE flag, so mprotecting
+	 * a MAP_NORESERVE private mapping to writable will now reserve.
+	 */
+	if ((newflags & VM_WRITE) &&
+	    !(vma->vm_flags & (VM_ACCOUNT|VM_WRITE|VM_SHARED))) {
+		charged = (end - start) >> PAGE_SHIFT;
+		if (!vm_enough_memory(charged))
+			return -ENOMEM;
+		newflags |= VM_ACCOUNT;
+	}
 	newprot = protection_map[newflags & 0xf];
 	if (start == vma->vm_start) {
 		if (end == vma->vm_end)
@@ -263,10 +283,10 @@
 		error = mprotect_fixup_end(vma, pprev, start, newflags, newprot);
 	else
 		error = mprotect_fixup_middle(vma, pprev, start, end, newflags, newprot);
-
-	if (error)
+	if (error) {
+		vm_unacct_memory(charged);
 		return error;
-
+	}
 	change_protection(vma, start, end, newprot);
 	return 0;
 }
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	Thu Aug  1 14:17:40 2002
+++ b/mm/mremap.c	Thu Aug  1 14:17:40 2002
@@ -1,7 +1,10 @@
 /*
- *	linux/mm/remap.c
+ *	mm/remap.c
  *
  *	(C) Copyright 1996 Linus Torvalds
+ *
+ *	Address space accounting code	<alan@redhat.com>
+ *	(C) Copyright 2002 Red Hat Inc, All Rights Reserved
  */
 
 #include <linux/mm.h>
@@ -18,8 +21,6 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
-extern int vm_enough_memory(long pages);
-
 static inline pte_t *get_one_pte_map_nested(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t * pgd;
@@ -149,6 +150,7 @@
 	struct mm_struct * mm = vma->vm_mm;
 	struct vm_area_struct * new_vma, * next, * prev;
 	int allocated_vma;
+	int split = 0;
 
 	new_vma = NULL;
 	next = find_vma_prev(mm, new_addr, &prev);
@@ -209,7 +211,26 @@
 				new_vma->vm_ops->open(new_vma);
 			insert_vm_struct(current->mm, new_vma);
 		}
+
+		/* Conceal VM_ACCOUNT so old reservation is not undone */
+		if (vma->vm_flags & VM_ACCOUNT) {
+			vma->vm_flags &= ~VM_ACCOUNT;
+			if (addr > vma->vm_start) {
+				if (addr + old_len < vma->vm_end)
+					split = 1;
+			} else if (addr + old_len == vma->vm_end)
+				vma = NULL;	/* it will be removed */
+		} else
+			vma = NULL;		/* nothing more to do */
+
 		do_munmap(current->mm, addr, old_len);
+
+		/* Restore VM_ACCOUNT if one or two pieces of vma left */
+		if (vma) {
+			vma->vm_flags |= VM_ACCOUNT;
+			if (split)
+				vma->vm_next->vm_flags |= VM_ACCOUNT;
+		}
 		current->mm->total_vm += new_len >> PAGE_SHIFT;
 		if (new_vma->vm_flags & VM_LOCKED) {
 			current->mm->locked_vm += new_len >> PAGE_SHIFT;
@@ -237,6 +258,7 @@
 {
 	struct vm_area_struct *vma;
 	unsigned long ret = -EINVAL;
+	unsigned long charged = 0;
 
 	if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
 		goto out;
@@ -272,12 +294,14 @@
 	/*
 	 * Always allow a shrinking remap: that just unmaps
 	 * the unnecessary pages..
+	 * do_munmap does all the needed commit accounting
 	 */
 	ret = addr;
 	if (old_len >= new_len) {
 		do_munmap(current->mm, addr+new_len, old_len - new_len);
 		if (!(flags & MREMAP_FIXED) || (new_addr == addr))
 			goto out;
+		old_len = new_len;
 	}
 
 	/*
@@ -305,11 +329,12 @@
 	if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
 	    > current->rlim[RLIMIT_AS].rlim_cur)
 		goto out;
-	/* Private writable mapping? Check memory availability.. */
-	if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE &&
-	    !(flags & MAP_NORESERVE)				 &&
-	    !vm_enough_memory((new_len - old_len) >> PAGE_SHIFT))
-		goto out;
+
+	if (vma->vm_flags & VM_ACCOUNT) {
+		charged = (new_len - old_len) >> PAGE_SHIFT;
+		if (!vm_enough_memory(charged))
+			goto out_nc;
+	}
 
 	/* old_len exactly to the end of the area..
 	 * And we're not relocating the area.
@@ -356,6 +381,9 @@
 		ret = move_vma(vma, addr, old_len, new_len, new_addr);
 	}
 out:
+	if (ret & ~PAGE_MASK)
+		vm_unacct_memory(charged);
+out_nc:
 	return ret;
 }
 
diff -Nru a/mm/numa.c b/mm/numa.c
--- a/mm/numa.c	Thu Aug  1 14:17:39 2002
+++ b/mm/numa.c	Thu Aug  1 14:17:39 2002
@@ -12,7 +12,7 @@
 int numnodes = 1;	/* Initialized for UMA platforms */
 
 static bootmem_data_t contig_bootmem_data;
-pg_data_t contig_page_data = { bdata: &contig_bootmem_data };
+pg_data_t contig_page_data = { .bdata = &contig_bootmem_data };
 
 #ifndef CONFIG_DISCONTIGMEM
 
@@ -44,17 +44,6 @@
 
 #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1))
 
-static spinlock_t node_lock = SPIN_LOCK_UNLOCKED;
-
-void show_free_areas_node(pg_data_t *pgdat)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&node_lock, flags);
-	show_free_areas_core(pgdat);
-	spin_unlock_irqrestore(&node_lock, flags);
-}
-
 /*
  * Nodes can be initialized parallely, in no particular order.
  */
@@ -106,23 +95,22 @@
 #ifdef CONFIG_NUMA
 	temp = NODE_DATA(numa_node_id());
 #else
-	spin_lock_irqsave(&node_lock, flags);
-	if (!next) next = pgdat_list;
+	if (!next)
+		next = pgdat_list;
 	temp = next;
-	next = next->node_next;
-	spin_unlock_irqrestore(&node_lock, flags);
+	next = next->pgdat_next;
 #endif
 	start = temp;
 	while (temp) {
 		if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
 			return(ret);
-		temp = temp->node_next;
+		temp = temp->pgdat_next;
 	}
 	temp = pgdat_list;
 	while (temp != start) {
 		if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
 			return(ret);
-		temp = temp->node_next;
+		temp = temp->pgdat_next;
 	}
 	return(0);
 }
diff -Nru a/mm/oom_kill.c b/mm/oom_kill.c
--- a/mm/oom_kill.c	Thu Aug  1 14:17:36 2002
+++ b/mm/oom_kill.c	Thu Aug  1 14:17:36 2002
@@ -18,7 +18,6 @@
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/timex.h>
 
 /* #define DEBUG */
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	Thu Aug  1 14:17:36 2002
+++ b/mm/page_alloc.c	Thu Aug  1 14:17:36 2002
@@ -477,22 +477,21 @@
  */
 unsigned int nr_free_pages(void)
 {
-	unsigned int i, sum = 0;
-	pg_data_t *pgdat;
+	unsigned int sum = 0;
+	zone_t *zone;
 
-	for (pgdat = pgdat_list; pgdat; pgdat = pgdat->node_next)
-		for (i = 0; i < MAX_NR_ZONES; ++i)
-			sum += pgdat->node_zones[i].free_pages;
+	for_each_zone(zone)
+		sum += zone->free_pages;
 
 	return sum;
 }
 
 static unsigned int nr_free_zone_pages(int offset)
 {
-	pg_data_t *pgdat = pgdat_list;
+	pg_data_t *pgdat;
 	unsigned int sum = 0;
 
-	do {
+	for_each_pgdat(pgdat) {
 		zonelist_t *zonelist = pgdat->node_zonelists + offset;
 		zone_t **zonep = zonelist->zones;
 		zone_t *zone;
@@ -503,9 +502,7 @@
 			if (size > high)
 				sum += size - high;
 		}
-
-		pgdat = pgdat->node_next;
-	} while (pgdat);
+	}
 
 	return sum;
 }
@@ -529,13 +526,12 @@
 #if CONFIG_HIGHMEM
 unsigned int nr_free_highpages (void)
 {
-	pg_data_t *pgdat = pgdat_list;
+	pg_data_t *pgdat;
 	unsigned int pages = 0;
 
-	while (pgdat) {
+	for_each_pgdat(pgdat)
 		pages += pgdat->node_zones[ZONE_HIGHMEM].free_pages;
-		pgdat = pgdat->node_next;
-	}
+
 	return pages;
 }
 #endif
@@ -566,8 +562,7 @@
 		ret->nr_active += ps->nr_active;
 		ret->nr_inactive += ps->nr_inactive;
 		ret->nr_page_table_pages += ps->nr_page_table_pages;
-		ret->nr_pte_chain_pages += ps->nr_pte_chain_pages;
-		ret->used_pte_chains_bytes += ps->used_pte_chains_bytes;
+		ret->nr_reverse_maps += ps->nr_reverse_maps;
 	}
 }
 
@@ -602,12 +597,11 @@
  * We also calculate the percentage fragmentation. We do this by counting the
  * memory on each free list with the exception of the first item on the list.
  */
-void show_free_areas_core(pg_data_t *pgdat)
+void show_free_areas(void)
 {
- 	unsigned int order;
-	unsigned type;
-	pg_data_t *tmpdat = pgdat;
+	pg_data_t *pgdat;
 	struct page_state ps;
+	int type;
 
 	get_page_state(&ps);
 
@@ -615,20 +609,20 @@
 		K(nr_free_pages()),
 		K(nr_free_highpages()));
 
-	while (tmpdat) {
-		zone_t *zone;
-		for (zone = tmpdat->node_zones;
-			       	zone < tmpdat->node_zones + MAX_NR_ZONES; zone++)
-			printk("Zone:%s freepages:%6lukB min:%6lukB low:%6lukB " 
-				       "high:%6lukB\n", 
-					zone->name,
-					K(zone->free_pages),
-					K(zone->pages_min),
-					K(zone->pages_low),
-					K(zone->pages_high));
-			
-		tmpdat = tmpdat->node_next;
-	}
+	for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
+		for (type = 0; type < MAX_NR_ZONES; ++type) {
+			zone_t *zone = &pgdat->node_zones[type];
+			printk("Zone:%s "
+				"freepages:%6lukB "
+				"min:%6lukB "
+				"low:%6lukB " 
+				"high:%6lukB\n", 
+				zone->name,
+				K(zone->free_pages),
+				K(zone->pages_min),
+				K(zone->pages_low),
+				K(zone->pages_high));
+		}
 
 	printk("( Active:%lu inactive:%lu dirty:%lu writeback:%lu free:%u )\n",
 		ps.nr_active,
@@ -637,40 +631,28 @@
 		ps.nr_writeback,
 		nr_free_pages());
 
-	for (type = 0; type < MAX_NR_ZONES; type++) {
-		struct list_head *head, *curr;
-		zone_t *zone = pgdat->node_zones + type;
- 		unsigned long nr, total, flags;
+	for (pgdat = pgdat_list; pgdat; pgdat = pgdat->pgdat_next)
+		for (type = 0; type < MAX_NR_ZONES; type++) {
+			list_t *elem;
+			zone_t *zone = &pgdat->node_zones[type];
+ 			unsigned long nr, flags, order, total = 0;
+
+			if (!zone->size)
+				continue;
 
-		total = 0;
-		if (zone->size) {
 			spin_lock_irqsave(&zone->lock, flags);
-		 	for (order = 0; order < MAX_ORDER; order++) {
-				head = &(zone->free_area + order)->free_list;
-				curr = head;
+			for (order = 0; order < MAX_ORDER; order++) {
 				nr = 0;
-				for (;;) {
-					curr = curr->next;
-					if (curr == head)
-						break;
-					nr++;
-				}
-				total += nr * (1 << order);
+				list_for_each(elem, &zone->free_area[order].free_list)
+					++nr;
+				total += nr << order;
 				printk("%lu*%lukB ", nr, K(1UL) << order);
 			}
 			spin_unlock_irqrestore(&zone->lock, flags);
+			printk("= %lukB)\n", K(total));
 		}
-		printk("= %lukB)\n", K(total));
-	}
 
-#ifdef SWAP_CACHE_INFO
 	show_swap_cache_info();
-#endif	
-}
-
-void show_free_areas(void)
-{
-	show_free_areas_core(pgdat_list);
 }
 
 /*
diff -Nru a/mm/page_io.c b/mm/page_io.c
--- a/mm/page_io.c	Thu Aug  1 14:17:36 2002
+++ b/mm/page_io.c	Thu Aug  1 14:17:36 2002
@@ -132,11 +132,11 @@
 }
 
 struct address_space_operations swap_aops = {
-	vm_writeback:	swap_vm_writeback,
-	writepage:	swap_writepage,
-	readpage:	swap_readpage,
-	sync_page:	block_sync_page,
-	set_page_dirty:	__set_page_dirty_nobuffers,
+	.vm_writeback	= swap_vm_writeback,
+	.writepage	= swap_writepage,
+	.readpage	= swap_readpage,
+	.sync_page	= block_sync_page,
+	.set_page_dirty	= __set_page_dirty_nobuffers,
 };
 
 /*
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	Thu Aug  1 14:17:36 2002
+++ b/mm/readahead.c	Thu Aug  1 14:17:36 2002
@@ -14,8 +14,8 @@
 #include <linux/backing-dev.h>
 
 struct backing_dev_info default_backing_dev_info = {
-	ra_pages:	(VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
-	state:		0,
+	.ra_pages	= (VM_MAX_READAHEAD * 1024) / PAGE_CACHE_SIZE,
+	.state		= 0,
 };
 
 /*
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	Thu Aug  1 14:17:41 2002
+++ b/mm/rmap.c	Thu Aug  1 14:17:41 2002
@@ -23,6 +23,8 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/swapops.h>
+#include <linux/slab.h>
+#include <linux/init.h>
 
 #include <asm/pgalloc.h>
 #include <asm/rmap.h>
@@ -50,10 +52,10 @@
 	pte_t * ptep;
 };
 
+static kmem_cache_t	*pte_chain_cache;
 static inline struct pte_chain * pte_chain_alloc(void);
 static inline void pte_chain_free(struct pte_chain *, struct pte_chain *,
 		struct page *);
-static void alloc_new_pte_chains(void);
 
 /**
  * page_referenced - test if the page was referenced
@@ -148,6 +150,7 @@
 	}
 
 	pte_chain_unlock(page);
+	inc_page_state(nr_reverse_maps);
 }
 
 /**
@@ -208,9 +211,9 @@
 #endif
 
 out:
+	dec_page_state(nr_reverse_maps);
 	pte_chain_unlock(page);
 	return;
-			
 }
 
 /**
@@ -355,27 +358,6 @@
  ** functions.
  **/
 
-struct pte_chain * pte_chain_freelist;
-spinlock_t pte_chain_freelist_lock = SPIN_LOCK_UNLOCKED;
-
-/* Maybe we should have standard ops for singly linked lists ... - Rik */
-static inline void pte_chain_push(struct pte_chain * pte_chain)
-{
-	pte_chain->ptep = NULL;
-	pte_chain->next = pte_chain_freelist;
-	pte_chain_freelist = pte_chain;
-}
-
-static inline struct pte_chain * pte_chain_pop(void)
-{
-	struct pte_chain *pte_chain;
-
-	pte_chain = pte_chain_freelist;
-	pte_chain_freelist = pte_chain->next;
-	pte_chain->next = NULL;
-
-	return pte_chain;
-}
 
 /**
  * pte_chain_free - free pte_chain structure
@@ -391,15 +373,12 @@
 static inline void pte_chain_free(struct pte_chain * pte_chain,
 		struct pte_chain * prev_pte_chain, struct page * page)
 {
-	mod_page_state(used_pte_chains_bytes, -sizeof(struct pte_chain));
 	if (prev_pte_chain)
 		prev_pte_chain->next = pte_chain->next;
 	else if (page)
 		page->pte.chain = pte_chain->next;
 
-	spin_lock(&pte_chain_freelist_lock);
-	pte_chain_push(pte_chain);
-	spin_unlock(&pte_chain_freelist_lock);
+	kmem_cache_free(pte_chain_cache, pte_chain);
 }
 
 /**
@@ -409,47 +388,20 @@
  * pte_chain structures as required.
  * Caller needs to hold the page's pte_chain_lock.
  */
-static inline struct pte_chain * pte_chain_alloc()
+static inline struct pte_chain *pte_chain_alloc(void)
 {
-	struct pte_chain * pte_chain;
-
-	spin_lock(&pte_chain_freelist_lock);
-
-	/* Allocate new pte_chain structs as needed. */
-	if (!pte_chain_freelist)
-		alloc_new_pte_chains();
-
-	/* Grab the first pte_chain from the freelist. */
-	pte_chain = pte_chain_pop();
-
-	spin_unlock(&pte_chain_freelist_lock);
-
-	mod_page_state(used_pte_chains_bytes, sizeof(struct pte_chain));
-	return pte_chain;
+	return kmem_cache_alloc(pte_chain_cache, GFP_ATOMIC);
 }
 
-/**
- * alloc_new_pte_chains - convert a free page to pte_chain structures
- *
- * Grabs a free page and converts it to pte_chain structures. We really
- * should pre-allocate these earlier in the pagefault path or come up
- * with some other trick.
- *
- * Note that we cannot use the slab cache because the pte_chain structure
- * is way smaller than the minimum size of a slab cache allocation.
- * Caller needs to hold the pte_chain_freelist_lock
- */
-static void alloc_new_pte_chains()
+void __init pte_chain_init(void)
 {
-	struct pte_chain * pte_chain = (void *) get_zeroed_page(GFP_ATOMIC);
-	int i = PAGE_SIZE / sizeof(struct pte_chain);
+	pte_chain_cache = kmem_cache_create(	"pte_chain",
+						sizeof(struct pte_chain),
+						0,
+						0,
+						NULL,
+						NULL);
 
-	if (pte_chain) {
-		inc_page_state(nr_pte_chain_pages);
-		for (; i-- > 0; pte_chain++)
-			pte_chain_push(pte_chain);
-	} else {
-		/* Yeah yeah, I'll fix the pte_chain allocation ... */
-		panic("Fix pte_chain allocation, you lazy bastard!\n");
-	}
+	if (!pte_chain_cache)
+		panic("failed to create pte_chain cache!\n");
 }
diff -Nru a/mm/shmem.c b/mm/shmem.c
--- a/mm/shmem.c	Thu Aug  1 14:17:40 2002
+++ b/mm/shmem.c	Thu Aug  1 14:17:40 2002
@@ -5,7 +5,8 @@
  *		 2000 Transmeta Corp.
  *		 2000-2001 Christoph Rohland
  *		 2000-2001 SAP AG
- * 
+ *		 2002 Red Hat Inc.
+ *
  * This file is released under the GPL.
  */
 
@@ -21,6 +22,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
@@ -35,6 +37,12 @@
 #define TMPFS_MAGIC	0x01021994
 
 #define ENTRIES_PER_PAGE (PAGE_CACHE_SIZE/sizeof(unsigned long))
+#define BLOCKS_PER_PAGE  (PAGE_CACHE_SIZE/512)
+
+#define SHMEM_MAX_INDEX  (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * (ENTRIES_PER_PAGE/2) * (ENTRIES_PER_PAGE+1))
+#define SHMEM_MAX_BYTES  ((unsigned long long)SHMEM_MAX_INDEX << PAGE_CACHE_SHIFT)
+
+#define VM_ACCT(size)    (((size) + PAGE_CACHE_SIZE - 1) >> PAGE_SHIFT)
 
 static inline struct shmem_sb_info *SHMEM_SB(struct super_block *sb)
 {
@@ -54,8 +62,6 @@
 
 static struct page *shmem_getpage_locked(struct shmem_inode_info *, struct inode *, unsigned long);
 
-#define BLOCKS_PER_PAGE (PAGE_CACHE_SIZE/512)
-
 /*
  * shmem_recalc_inode - recalculate the size of an inode
  *
@@ -131,9 +137,6 @@
  * 	      	       +-> 48-51
  * 	      	       +-> 52-55
  */
-
-#define SHMEM_MAX_BLOCKS (SHMEM_NR_DIRECT + ENTRIES_PER_PAGE * ENTRIES_PER_PAGE/2*(ENTRIES_PER_PAGE+1))
-
 static swp_entry_t * shmem_swp_entry (struct shmem_inode_info *info, unsigned long index, unsigned long page) 
 {
 	unsigned long offset;
@@ -186,7 +189,7 @@
 	unsigned long page = 0;
 	swp_entry_t * res;
 
-	if (index >= SHMEM_MAX_BLOCKS)
+	if (index >= SHMEM_MAX_INDEX)
 		return ERR_PTR(-EFBIG);
 
 	if (info->next_index <= index)
@@ -358,15 +361,46 @@
 	up(&info->sem);
 }
 
+static int shmem_notify_change(struct dentry * dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	long change = 0;
+	int error;
+
+	if ((attr->ia_valid & ATTR_SIZE) && (attr->ia_size <= SHMEM_MAX_BYTES)) {
+		/*
+	 	 * Account swap file usage based on new file size,
+		 * but just let vmtruncate fail on out-of-range sizes.
+	 	 */
+		change = VM_ACCT(attr->ia_size) - VM_ACCT(inode->i_size);
+		if (change > 0) {
+			if (!vm_enough_memory(change))
+				return -ENOMEM;
+		} else
+			vm_unacct_memory(-change);
+	}
+
+	error = inode_change_ok(inode, attr);
+	if (!error)
+		error = inode_setattr(inode, attr);
+	if (error)
+		vm_unacct_memory(change);
+	return error;
+}
+
+
 static void shmem_delete_inode(struct inode * inode)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+	struct shmem_inode_info *info = SHMEM_I(inode);
 
-	inode->i_size = 0;
-	if (inode->i_op->truncate == shmem_truncate){ 
-		spin_lock (&shmem_ilock);
-		list_del (&SHMEM_I(inode)->list);
-		spin_unlock (&shmem_ilock);
+	if (inode->i_op->truncate == shmem_truncate) {
+		spin_lock(&shmem_ilock);
+		list_del(&info->list);
+		spin_unlock(&shmem_ilock);
+		if (info->flags & VM_ACCOUNT)
+			vm_unacct_memory(VM_ACCT(inode->i_size));
+		inode->i_size = 0;
 		shmem_truncate (inode);
 	}
 	spin_lock (&sbinfo->stat_lock);
@@ -494,7 +528,7 @@
 	index = page->index;
 	inode = mapping->host;
 	info = SHMEM_I(inode);
-	if (info->locked)
+	if (info->flags & VM_LOCKED)
 		return fail_writepage(page);
 	swap = get_swap_page();
 	if (!swap.val)
@@ -711,9 +745,12 @@
 	struct inode * inode = file->f_dentry->d_inode;
 	struct shmem_inode_info * info = SHMEM_I(inode);
 
-	down(&info->sem);
-	info->locked = lock;
-	up(&info->sem);
+	spin_lock(&info->lock);
+	if (lock)
+		info->flags |= VM_LOCKED;
+	else
+		info->flags &= ~VM_LOCKED;
+	spin_unlock(&info->lock);
 }
 
 static int shmem_mmap(struct file * file, struct vm_area_struct * vma)
@@ -760,7 +797,7 @@
 		memset (info->i_direct, 0, sizeof(info->i_direct));
 		info->i_indirect = NULL;
 		info->swapped = 0;
-		info->locked = 0;
+		info->flags = VM_ACCOUNT;
 		switch (mode & S_IFMT) {
 		default:
 			init_special_inode(inode, mode, dev);
@@ -824,6 +861,7 @@
 	unsigned long	written;
 	long		status;
 	int		err;
+	loff_t		maxpos;
 
 	if ((ssize_t) count < 0)
 		return -EINVAL;
@@ -836,12 +874,12 @@
 	pos = *ppos;
 	err = -EINVAL;
 	if (pos < 0)
-		goto out;
+		goto out_nc;
 
 	err = file->f_error;
 	if (err) {
 		file->f_error = 0;
-		goto out;
+		goto out_nc;
 	}
 
 	written = 0;
@@ -849,6 +887,17 @@
 	if (file->f_flags & O_APPEND)
 		pos = inode->i_size;
 
+	maxpos = inode->i_size;
+	if (pos + count > inode->i_size) {
+		maxpos = pos + count;
+		if (maxpos > SHMEM_MAX_BYTES)
+			maxpos = SHMEM_MAX_BYTES;
+		if (!vm_enough_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size))) {
+			err = -ENOMEM;
+			goto out_nc;
+		}
+	}
+
 	/*
 	 * Check whether we've reached the file size limit.
 	 */
@@ -938,6 +987,10 @@
 
 	err = written ? written : status;
 out:
+	/* Short writes give back address space */
+	if (inode->i_size != maxpos)
+		vm_unacct_memory(VM_ACCT(maxpos) - VM_ACCT(inode->i_size));
+out_nc:
 	up(&inode->i_sem);
 	return err;
 fail_write:
@@ -1191,10 +1244,15 @@
 		memcpy(info, symname, len);
 		inode->i_op = &shmem_symlink_inline_operations;
 	} else {
+		if (!vm_enough_memory(VM_ACCT(1))) {
+			iput(inode);
+			return -ENOMEM;
+		}
 		down(&info->sem);
 		page = shmem_getpage_locked(info, inode, 0);
 		if (IS_ERR(page)) {
 			up(&info->sem);
+			vm_unacct_memory(VM_ACCT(1));
 			iput(inode);
 			return PTR_ERR(page);
 		}
@@ -1254,14 +1312,14 @@
 }
 
 static struct inode_operations shmem_symlink_inline_operations = {
-	readlink:	shmem_readlink_inline,
-	follow_link:	shmem_follow_link_inline,
+	.readlink	= shmem_readlink_inline,
+	.follow_link	= shmem_follow_link_inline,
 };
 
 static struct inode_operations shmem_symlink_inode_operations = {
-	truncate:	shmem_truncate,
-	readlink:	shmem_readlink,
-	follow_link:	shmem_follow_link,
+	.truncate	= shmem_truncate,
+	.readlink	= shmem_readlink,
+	.follow_link	= shmem_follow_link,
 };
 
 static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long * blocks, unsigned long *inodes)
@@ -1383,7 +1441,7 @@
 	sbinfo->free_blocks = blocks;
 	sbinfo->max_inodes = inodes;
 	sbinfo->free_inodes = inodes;
-	sb->s_maxbytes = (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT;
+	sb->s_maxbytes = SHMEM_MAX_BYTES;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_magic = TMPFS_MAGIC;
@@ -1462,51 +1520,52 @@
 }
 
 static struct address_space_operations shmem_aops = {
-	writepage:	shmem_writepage,
-	set_page_dirty:	__set_page_dirty_nobuffers,
+	.writepage	= shmem_writepage,
+	.set_page_dirty	= __set_page_dirty_nobuffers,
 };
 
 static struct file_operations shmem_file_operations = {
-	mmap:	shmem_mmap,
+	.mmap		= shmem_mmap,
 #ifdef CONFIG_TMPFS
-	read:	shmem_file_read,
-	write:	shmem_file_write,
-	fsync:	shmem_sync_file,
+	.read		= shmem_file_read,
+	.write		= shmem_file_write,
+	.fsync		= shmem_sync_file,
 #endif
 };
 
 static struct inode_operations shmem_inode_operations = {
-	truncate:	shmem_truncate,
+	.truncate	= shmem_truncate,
+	.setattr	= shmem_notify_change,
 };
 
 static struct inode_operations shmem_dir_inode_operations = {
 #ifdef CONFIG_TMPFS
-	create:		shmem_create,
-	lookup:		simple_lookup,
-	link:		shmem_link,
-	unlink:		shmem_unlink,
-	symlink:	shmem_symlink,
-	mkdir:		shmem_mkdir,
-	rmdir:		shmem_rmdir,
-	mknod:		shmem_mknod,
-	rename:		shmem_rename,
+	.create		= shmem_create,
+	.lookup		= simple_lookup,
+	.link		= shmem_link,
+	.unlink		= shmem_unlink,
+	.symlink	= shmem_symlink,
+	.mkdir		= shmem_mkdir,
+	.rmdir		= shmem_rmdir,
+	.mknod		= shmem_mknod,
+	.rename		= shmem_rename,
 #endif
 };
 
 static struct super_operations shmem_ops = {
-	alloc_inode:	shmem_alloc_inode,
-	destroy_inode:	shmem_destroy_inode,
+	.alloc_inode	= shmem_alloc_inode,
+	.destroy_inode	= shmem_destroy_inode,
 #ifdef CONFIG_TMPFS
-	statfs:		shmem_statfs,
-	remount_fs:	shmem_remount_fs,
+	.statfs		= shmem_statfs,
+	.remount_fs	= shmem_remount_fs,
 #endif
-	delete_inode:	shmem_delete_inode,
-	drop_inode:	generic_delete_inode,
-	put_super:	shmem_put_super,
+	.delete_inode	= shmem_delete_inode,
+	.drop_inode	= generic_delete_inode,
+	.put_super	= shmem_put_super,
 };
 
 static struct vm_operations_struct shmem_vm_ops = {
-	nopage:	shmem_nopage,
+	.nopage		= shmem_nopage,
 };
 
 static struct super_block *shmem_get_sb(struct file_system_type *fs_type,
@@ -1518,17 +1577,17 @@
 #ifdef CONFIG_TMPFS
 /* type "shm" will be tagged obsolete in 2.5 */
 static struct file_system_type shmem_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"shmem",
-	get_sb:		shmem_get_sb,
-	kill_sb:	kill_litter_super,
+	.owner		= THIS_MODULE,
+	.name		= "shmem",
+	.get_sb		= shmem_get_sb,
+	.kill_sb	= kill_litter_super,
 };
 #endif
 static struct file_system_type tmpfs_fs_type = {
-	owner:		THIS_MODULE,
-	name:		"tmpfs",
-	get_sb:		shmem_get_sb,
-	kill_sb:	kill_litter_super,
+	.owner		= THIS_MODULE,
+	.name		= "tmpfs",
+	.get_sb		= shmem_get_sb,
+	.kill_sb	= kill_litter_super,
 };
 static struct vfsmount *shm_mnt;
 
@@ -1598,28 +1657,28 @@
  * @size: size to be set for the file
  *
  */
-struct file *shmem_file_setup(char * name, loff_t size)
+struct file *shmem_file_setup(char * name, loff_t size, unsigned long flags)
 {
 	int error;
 	struct file *file;
 	struct inode * inode;
 	struct dentry *dentry, *root;
 	struct qstr this;
-	int vm_enough_memory(long pages);
 
-	if (size > (unsigned long long) SHMEM_MAX_BLOCKS << PAGE_CACHE_SHIFT)
+	if (size > SHMEM_MAX_BYTES)
 		return ERR_PTR(-EINVAL);
 
-	if (!vm_enough_memory((size) >> PAGE_CACHE_SHIFT))
+	if ((flags & VM_ACCOUNT) && !vm_enough_memory(VM_ACCT(size)))
 		return ERR_PTR(-ENOMEM);
 
+	error = -ENOMEM;
 	this.name = name;
 	this.len = strlen(name);
 	this.hash = 0; /* will go */
 	root = shm_mnt->mnt_root;
 	dentry = d_alloc(root, &this);
 	if (!dentry)
-		return ERR_PTR(-ENOMEM);
+		goto put_memory;
 
 	error = -ENFILE;
 	file = get_empty_filp();
@@ -1631,22 +1690,26 @@
 	if (!inode) 
 		goto close_file;
 
+	SHMEM_I(inode)->flags &= flags;
 	d_instantiate(dentry, inode);
-	dentry->d_inode->i_size = size;
-	shmem_truncate(inode);
+	inode->i_size = size;
+	inode->i_nlink = 0;	/* It is unlinked */
 	file->f_vfsmnt = mntget(shm_mnt);
 	file->f_dentry = dentry;
 	file->f_op = &shmem_file_operations;
 	file->f_mode = FMODE_WRITE | FMODE_READ;
-	inode->i_nlink = 0;	/* It is unlinked */
 	return(file);
 
 close_file:
 	put_filp(file);
 put_dentry:
 	dput (dentry);
+put_memory:
+	if (flags & VM_ACCOUNT)
+		vm_unacct_memory(VM_ACCT(size));
 	return ERR_PTR(error);	
 }
+
 /*
  * shmem_zero_setup - setup a shared anonymous mapping
  *
@@ -1657,7 +1720,7 @@
 	struct file *file;
 	loff_t size = vma->vm_end - vma->vm_start;
 	
-	file = shmem_file_setup("dev/zero", size);
+	file = shmem_file_setup("dev/zero", size, vma->vm_flags);
 	if (IS_ERR(file))
 		return PTR_ERR(file);
 
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	Thu Aug  1 14:17:41 2002
+++ b/mm/slab.c	Thu Aug  1 14:17:41 2002
@@ -126,7 +126,7 @@
  * Bufctl's are used for linking objs within a slab
  * linked offsets.
  *
- * This implementaion relies on "struct page" for locating the cache &
+ * This implementation relies on "struct page" for locating the cache &
  * slab an object belongs to.
  * This allows the bufctl structure to be small (one int), but limits
  * the number of objects a slab (not a cache) can contain when off-slab
@@ -384,14 +384,14 @@
 
 /* internal cache of cache description objs */
 static kmem_cache_t cache_cache = {
-	slabs_full:	LIST_HEAD_INIT(cache_cache.slabs_full),
-	slabs_partial:	LIST_HEAD_INIT(cache_cache.slabs_partial),
-	slabs_free:	LIST_HEAD_INIT(cache_cache.slabs_free),
-	objsize:	sizeof(kmem_cache_t),
-	flags:		SLAB_NO_REAP,
-	spinlock:	SPIN_LOCK_UNLOCKED,
-	colour_off:	L1_CACHE_BYTES,
-	name:		"kmem_cache",
+	.slabs_full	= LIST_HEAD_INIT(cache_cache.slabs_full),
+	.slabs_partial	= LIST_HEAD_INIT(cache_cache.slabs_partial),
+	.slabs_free	= LIST_HEAD_INIT(cache_cache.slabs_free),
+	.objsize	= sizeof(kmem_cache_t),
+	.flags		= SLAB_NO_REAP,
+	.spinlock	= SPIN_LOCK_UNLOCKED,
+	.colour_off	= L1_CACHE_BYTES,
+	.name		= "kmem_cache",
 };
 
 /* Guard access to the cache-chain. */
@@ -1647,6 +1647,15 @@
 	local_irq_restore(flags);
 }
 
+unsigned int kmem_cache_size(kmem_cache_t *cachep)
+{
+#if DEBUG
+	if (cachep->flags & SLAB_RED_ZONE)
+		return (cachep->objsize - 2*BYTES_PER_WORD);
+#endif
+	return cachep->objsize;
+}
+
 kmem_cache_t * kmem_find_general_cachep (size_t size, int gfpflags)
 {
 	cache_sizes_t *csizep = cache_sizes;
@@ -2044,10 +2053,10 @@
  */
 
 struct seq_operations slabinfo_op = {
-	start:	s_start,
-	next:	s_next,
-	stop:	s_stop,
-	show:	s_show
+	.start	= s_start,
+	.next	= s_next,
+	.stop	= s_stop,
+	.show	= s_show,
 };
 
 #define MAX_SLABINFO_WRITE 128
diff -Nru a/mm/swap.c b/mm/swap.c
--- a/mm/swap.c	Thu Aug  1 14:17:40 2002
+++ b/mm/swap.c	Thu Aug  1 14:17:40 2002
@@ -16,7 +16,6 @@
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
 
@@ -26,12 +25,6 @@
 
 /* How many pages do we try to swap or page in/out together? */
 int page_cluster;
-
-pager_daemon_t pager_daemon = {
-	512,	/* base number for calculating the number of tries */
-	SWAP_CLUSTER_MAX,	/* minimum number of tries */
-	8,	/* do swap I/O in clusters of this size */
-};
 
 /*
  * Move an inactive page to the active list.
diff -Nru a/mm/swap_state.c b/mm/swap_state.c
--- a/mm/swap_state.c	Thu Aug  1 14:17:40 2002
+++ b/mm/swap_state.c	Thu Aug  1 14:17:40 2002
@@ -10,7 +10,6 @@
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
@@ -23,27 +22,26 @@
  * avoid some special-casing in other parts of the kernel.
  */
 static struct inode swapper_inode = {
-	i_mapping:	&swapper_space,
+	.i_mapping	= &swapper_space,
 };
 
 extern struct address_space_operations swap_aops;
 
 struct address_space swapper_space = {
-	page_tree:	RADIX_TREE_INIT(GFP_ATOMIC),
-	page_lock:	RW_LOCK_UNLOCKED,
-	clean_pages:	LIST_HEAD_INIT(swapper_space.clean_pages),
-	dirty_pages:	LIST_HEAD_INIT(swapper_space.dirty_pages),
-	io_pages:	LIST_HEAD_INIT(swapper_space.io_pages),
-	locked_pages:	LIST_HEAD_INIT(swapper_space.locked_pages),
-	host:		&swapper_inode,
-	a_ops:		&swap_aops,
-	i_shared_lock:	SPIN_LOCK_UNLOCKED,
-	private_lock:	SPIN_LOCK_UNLOCKED,
-	private_list:	LIST_HEAD_INIT(swapper_space.private_list),
+	.page_tree	= RADIX_TREE_INIT(GFP_ATOMIC),
+	.page_lock	= RW_LOCK_UNLOCKED,
+	.clean_pages	= LIST_HEAD_INIT(swapper_space.clean_pages),
+	.dirty_pages	= LIST_HEAD_INIT(swapper_space.dirty_pages),
+	.io_pages	= LIST_HEAD_INIT(swapper_space.io_pages),
+	.locked_pages	= LIST_HEAD_INIT(swapper_space.locked_pages),
+	.host		= &swapper_inode,
+	.a_ops		= &swap_aops,
+	.i_shared_lock	= SPIN_LOCK_UNLOCKED,
+	.private_lock	= SPIN_LOCK_UNLOCKED,
+	.private_list	= LIST_HEAD_INIT(swapper_space.private_list),
 };
 
-#ifdef SWAP_CACHE_INFO
-#define INC_CACHE_INFO(x)	(swap_cache_info.x++)
+#define INC_CACHE_INFO(x)	do { swap_cache_info.x++; } while (0)
 
 static struct {
 	unsigned long add_total;
@@ -61,9 +59,6 @@
 		swap_cache_info.find_success, swap_cache_info.find_total,
 		swap_cache_info.noent_race, swap_cache_info.exist_race);
 }
-#else
-#define INC_CACHE_INFO(x)	do { } while (0)
-#endif
 
 int add_to_swap_cache(struct page *page, swp_entry_t entry)
 {
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	Thu Aug  1 14:17:37 2002
+++ b/mm/swapfile.c	Thu Aug  1 14:17:37 2002
@@ -10,7 +10,6 @@
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/namei.h>
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	Thu Aug  1 14:17:36 2002
+++ b/mm/vmscan.c	Thu Aug  1 14:17:36 2002
@@ -15,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
-#include <linux/swapctl.h>
 #include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
@@ -200,8 +199,8 @@
 			 * so the direct writes to the page cannot get lost.
 			 */
 			int (*writeback)(struct page *, int *);
-			const int nr_pages = SWAP_CLUSTER_MAX;
-			int nr_to_write = nr_pages;
+			const int cluster_size = SWAP_CLUSTER_MAX;
+			int nr_to_write = cluster_size;
 
 			writeback = mapping->a_ops->vm_writeback;
 			if (writeback == NULL)
@@ -209,7 +208,7 @@
 			page_cache_get(page);
 			spin_unlock(&pagemap_lru_lock);
 			(*writeback)(page, &nr_to_write);
-			max_scan -= (nr_pages - nr_to_write);
+			max_scan -= (cluster_size - nr_to_write);
 			page_cache_release(page);
 			spin_lock(&pagemap_lru_lock);
 			continue;
@@ -471,7 +470,7 @@
 		pgdat = pgdat_list;
 		do
 			need_more_balance |= kswapd_balance_pgdat(pgdat);
-		while ((pgdat = pgdat->node_next));
+		while ((pgdat = pgdat->pgdat_next));
 	} while (need_more_balance);
 }
 
@@ -499,7 +498,7 @@
 		if (kswapd_can_sleep_pgdat(pgdat))
 			continue;
 		return 0;
-	} while ((pgdat = pgdat->node_next));
+	} while ((pgdat = pgdat->pgdat_next));
 
 	return 1;
 }
diff -Nru a/net/802/Makefile b/net/802/Makefile
--- a/net/802/Makefile	Thu Aug  1 14:17:40 2002
+++ b/net/802/Makefile	Thu Aug  1 14:17:40 2002
@@ -6,6 +6,7 @@
 
 obj-y			:= p8023.o
 
+# Check the p8022 selections against net/core/Makefile.
 obj-$(CONFIG_SYSCTL)	+= sysctl_net_802.o
 obj-$(CONFIG_LLC)	+= p8022.o psnap.o llc_sendpdu.o llc_utility.o \
 			   		   cl2llc.o llc_macinit.o	
diff -Nru a/net/Config.in b/net/Config.in
--- a/net/Config.in	Thu Aug  1 14:17:39 2002
+++ b/net/Config.in	Thu Aug  1 14:17:39 2002
@@ -26,9 +26,6 @@
 	 source net/ipv6/Config.in
       fi
    fi
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      source net/khttpd/Config.in
-   fi
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    bool 'Asynchronous Transfer Mode (ATM) (EXPERIMENTAL)' CONFIG_ATM
diff -Nru a/net/Makefile b/net/Makefile
--- a/net/Makefile	Thu Aug  1 14:17:40 2002
+++ b/net/Makefile	Thu Aug  1 14:17:40 2002
@@ -16,7 +16,6 @@
 obj-$(CONFIG_INET)		+= ipv4/
 obj-$(CONFIG_UNIX)		+= unix/
 obj-$(CONFIG_IPV6)		+= ipv6/
-obj-$(CONFIG_KHTTPD)		+= khttpd/
 obj-$(CONFIG_PACKET)		+= packet/
 obj-$(CONFIG_NET_SCHED)		+= sched/
 obj-$(CONFIG_BRIDGE)		+= bridge/
diff -Nru a/net/core/Makefile b/net/core/Makefile
--- a/net/core/Makefile	Thu Aug  1 14:17:41 2002
+++ b/net/core/Makefile	Thu Aug  1 14:17:41 2002
@@ -2,7 +2,7 @@
 # Makefile for the Linux networking core.
 #
 
-export-objs := ext8022.o netfilter.o profile.o
+export-objs := ext8022.o
 
 obj-y := sock.o skbuff.o iovec.o datagram.o scm.o
 
@@ -16,7 +16,8 @@
 
 obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o
 
-ifneq ($(CONFIG_LLC),n)
+# See p8022 in net/802/Makefile for config options to check
+ifneq ($(CONFIG_LLC)$(CONFIG_TR)$(CONFIG_IPX)$(CONFIG_ATALK),)
 obj-y += ext8022.o
 endif
 
diff -Nru a/net/ipv4/Makefile b/net/ipv4/Makefile
--- a/net/ipv4/Makefile	Thu Aug  1 14:17:39 2002
+++ b/net/ipv4/Makefile	Thu Aug  1 14:17:39 2002
@@ -2,8 +2,6 @@
 # Makefile for the Linux TCP/IP (INET) layer.
 #
 
-export-objs = ipip.o ip_gre.o
-
 obj-y     := utils.o route.o inetpeer.o proc.o protocol.o \
 	     ip_input.o ip_fragment.o ip_forward.o ip_options.o \
 	     ip_output.o ip_sockglue.o \
diff -Nru a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
--- a/net/ipv4/ipconfig.c	Thu Aug  1 14:17:36 2002
+++ b/net/ipv4/ipconfig.c	Thu Aug  1 14:17:36 2002
@@ -469,7 +469,7 @@
 
 
 /*
- *  Send RARP request packet over a signle interface.
+ *  Send RARP request packet over a single interface.
  */
 static void __init ic_rarp_send_if(struct ic_device *d)
 {
diff -Nru a/net/ipx/Makefile b/net/ipx/Makefile
--- a/net/ipx/Makefile	Thu Aug  1 14:17:37 2002
+++ b/net/ipx/Makefile	Thu Aug  1 14:17:37 2002
@@ -2,7 +2,7 @@
 # Makefile for the Linux IPX layer.
 #
 
-export-objs = af_ipx.o af_spx.o
+export-objs = af_ipx.o
 
 obj-$(CONFIG_IPX) += ipx.o
 
diff -Nru a/net/khttpd/Config.help b/net/khttpd/Config.help
--- a/net/khttpd/Config.help	Thu Aug  1 14:17:40 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,18 +0,0 @@
-CONFIG_KHTTPD
-  The kernel httpd acceleration daemon (kHTTPd) is a (limited) web
-  server built into the kernel. It is limited since it can only serve
-  files from the file system and cannot deal with executable content
-  such as CGI scripts. Serving files is sped up if you use kHTTPd.
-  If kHTTPd is not able to fulfill a request, it can transparently
-  pass it through to a user space web server such as apache.
-
-  Saying "M" here builds the kHTTPd module; this is NOT enough to have
-  a working kHTTPd. For safety reasons, the module has to be activated
-  by doing a "echo 1 > /proc/sys/net/khttpd/start" after inserting the
-  module.
-
-  Before using this, read the README in net/khttpd !
-
-  The kHTTPd is experimental. Be careful when using it on a production
-  machine. Also note that kHTTPd doesn't support virtual servers yet.
-
diff -Nru a/net/khttpd/Config.in b/net/khttpd/Config.in
--- a/net/khttpd/Config.in	Thu Aug  1 14:17:41 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,4 +0,0 @@
-#
-# kHTTPd
-#
-tristate '  Kernel httpd acceleration (EXPERIMENTAL)' CONFIG_KHTTPD
diff -Nru a/net/khttpd/Makefile b/net/khttpd/Makefile
--- a/net/khttpd/Makefile	Thu Aug  1 14:17:41 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,22 +0,0 @@
-#
-# Makefile for kHTTPd
-#
-
-obj-$(CONFIG_KHTTPD) += khttpd.o
-
-khttpd-objs := 	main.o accept.o datasending.o logging.o misc.o rfc.o \
-		rfc_time.o security.o sockets.o sysctl.o userspace.o \
-		waitheaders.o
-
-host-progs := make_times_h
-
-include $(TOPDIR)/Rules.make
-
-# Dependencies on generated files need to be listed explicitly
-
-$(obj)/rfc_time.o: $(obj)/times.h
-
-# Generated files
-
-$(obj)/times.h: $(obj)/make_times_h
-	$(obj)/make_times_h >$@
diff -Nru a/net/khttpd/README b/net/khttpd/README
--- a/net/khttpd/README	Thu Aug  1 14:17:41 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,224 +0,0 @@
-=====
-
-kHTTPd  -  Kernel httpd accelerator
-
-(C) 1999 by Arjan van de Ven
-Licensed under the terms of the GNU General Public License
-
-=====
-
-
-1. Introduction
----------------
-   kHTTPd is a http-daemon (webserver) for Linux. kHTTPd is different from 
-   other webservers in that it runs from within the Linux-kernel as a module 
-   (device-driver).
-
-   kHTTPd handles only static (file based) web-pages, and passes all requests
-   for non-static information to a regular userspace-webserver such as Apache or 
-   Zeus. The userspace-daemon doesn't have to be altered in any way.
-
-   Static web-pages are not a very complex thing to serve, but these are very
-   important nevertheless, since virtually all images are static, and a large
-   portion of the html-pages are static also. A "regular" webserver has little
-   added value for static pages, it is simply a "copy file to network"-operation.
-   This can be done very efficiently from within the Linux-kernel, for example 
-   the nfs (network file system) daemon performs a similar task and also runs 
-   in the kernel.
-
-   By "accelerating" the simple case within the kernel, userspace daemons can
-   do what they are very good at: Generating user-specific, dynamic content.
-
-   Note: This document sometimes uses "Apache" instead of "any webserver you
-   ever might want to use", just for reasons of readability.
-   
-
-2. Quick Start  
---------------
-
-   1) compile and load the module
-   2) configure the module in /proc/sys/net/khttpd if needed
-   3) echo 1 > /proc/sys/net/khttpd/start
-
-   unloading:
- 
-   echo 1 > /proc/sys/net/khttpd/stop
-   echo 1 > /proc/sys/net/khttpd/unload 
-   rmmod khttpd
-   
-
-
-3. Configuration 
-----------------
-
-   Modes of operation
-   ==================
-
-
-   There are two recommended modes of operation:
-
-   1) "Apache" is main webserver, kHTTPd is assistant
-	clientport   -> 80
-  	serverport   -> 8080 (or whatever)
-
-   2) kHTTPd is main webserver, "Apache" is assistant
-	clientport   -> 8080 (or whatever)
- 	serverport   -> 80
-
-   
-   Configuring kHTTPd
-   ==================
-
-   Before you can start using kHTTPd, you have to configure it. This
-   is done through the /proc filesystem, and can thus be done from inside
-   a script. Most parameters can only be set when kHTTPd is not active.
-
-   The following things need configuration:
-
-   1) The port where kHTTPd should listen for requests
-   2) The port (on "localhost") where "Apache" is listening
-   3) The location of the documents (documentroot)
-   4) The strings that indicate dynamic content (optional)
-      [  "cgi-bin" is added by default ]
-
-   It is very important that the documentroot for kHTTPd matches the
-   documentroot for the userspace-daemon, as kHTTPd might "redirect"
-   any request to this userspace-daemon.
-
-   A typical script (for the first mode of operation) to do this would 
-   look like:
-
-#!/bin/sh
-modprobe khttpd
-echo 80 > /proc/sys/net/khttpd/clientport
-echo 8080 > /proc/sys/net/khttpd/serverport
-echo /var/www > /proc/sys/net/khttpd/documentroot
-echo php3 > /proc/sys/net/khttpd/dynamic
-echo shtml > /proc/sys/net/khttpd/dynamic
-echo 1 > /proc/sys/net/khttpd/start
-
-   For the second mode of operation, this would be:
-
-#!/bin/sh
-modprobe khttpd
-echo 8080 > /proc/sys/net/khttpd/clientport
-echo 80 > /proc/sys/net/khttpd/serverport
-echo /var/www > /proc/sys/net/khttpd/documentroot
-echo php3 > /proc/sys/net/khttpd/dynamic
-echo shtml > /proc/sys/net/khttpd/dynamic
-echo 1 > /proc/sys/net/khttpd/start
-
-   In this case, you also have to change the configuration of the 
-   userspace-daemon. For Apache, you do this by changing
-
-   Port 80
-
-   to 
-
-   Port 8080
-
-
-   
-   Stopping kHTTPd
-   ===============
-   In order to change the configuration, you should stop kHTTPd by typing
-   echo 1 > /proc/sys/net/khttpd/stop
-   on a command-prompt.
-
-   If you want to unload the module, you should type
-   echo 1 > /proc/sys/net/khttpd/unload
-   after stopping kHTTPd first.
-
-   If this doesn't work fast enough for you (the commands above can wait for 
-   a remote connection to close down), you can send the daemons a "HUP"
-   signal after you told them to stop. This will cause the daemon-threads to
-   stop immediately. 
-
-   Note that the daemons will restart immediately if they are not told to
-   stop.
-
-   
-
-4. Permissions
---------------
-   The security model of kHTTPd is very strict. It can be, since there is a 
-   userspace daemon that can handle the complex exceptions. 
-
-   kHTTPd only serves a file if
-
-	1)  There is no "?" in the URL
-	2)  The URL starts with a "/"
-	3)  The file indicated by the URL exists
-	4)  The file is world-readable (*)
-	5)  The file is not a directory, executable or has the Sticky-bit
-	    set (*)
-	6)  The URL doesn't contain any "forbidden" substrings such as ".."
-	    and "cgi-bin" (*)
-	7)  The mime-type is known (*)
-
-   The items marked with a (*) are configurable through the
-   sysctl-parameters in /proc/sys/net/khttpd.
-
-
-   In all cases where any of the above conditions isn't met, the
-   userspace-daemon is handed the request.
-
-
-
-5. Parameters
--------------
-   The following parameters are settable through /proc/sys/net/khttpd:
- 
-	Name		Default		Description
-
-	serverport	8080		The port where kHTTPd listens on
-
-	clientport	80		The port of the userspace
-					http-daemon
-
-	threads		2		The number of server-threads. Should
-					be 1 per CPU for small websites, 2
-					per CPU for big (the active files
-					do not fit in the RAM) websites.
-
-	documentroot	/var/www	the directory where the
-					document-files are
-
-	start		0		Set to 1 to start kHTTPd 
-					(this also resets "stop" to 0)
-
-	stop		0		Set to 1 to stop kHTTPd
-					(this also resets "start" to 0)
-
-	unload		0		Set to 1 to prepare kHTTPd for
-					unloading of the module
-
-	sloppymime	0		If set to 1, unknown mime-types are
-					set to text/html. If set to 0,
-					files with unknown mime-types are
-					handled by the userspace daemon
-
-	perm_required	S_IROTH		Minimum permissions required
-					(for values see "man 2 stat")
-	
-	perm_forbid	dir+sticky+	Permission-mask with "forbidden"
-			execute		permissions.
-					(for values see "man 2 stat")
-
-	dynamic		cgi-bin ..	Strings that, if they are a subset
-					of the URL, indicate "dynamic
-					content"
-
-	maxconnect	1000		Maximum number of concurrent
-					connections
-
-6. More information
--------------------
-   More information about the architecture of kHTTPd, the mailinglist and
-   configuration-examples can be found at the kHTTPd homepage:
-
-	http://www.fenrus.demon.nl
-
-   Bugreports, patches, etc can be send to the mailinglist
-   (khttpd-users@zgp.org) or to khttpd@fenrus.demon.nl
-
diff -Nru a/net/khttpd/accept.c b/net/khttpd/accept.c
--- a/net/khttpd/accept.c	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,129 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Accept connections
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-#include "structure.h"
-#include "prototypes.h"
-#include "sysctl.h"
-
-#include <linux/smp_lock.h>
-
-/*
-
-Purpose:
-
-AcceptConnections puts all "accepted" connections in the 
-"WaitForHeader" queue.
-
-Return value:
-	The number of accepted connections
-*/
-
-
-int AcceptConnections(const int CPUNR, struct socket *Socket)
-{
-	struct tcp_opt *tp;
-	struct http_request *NewRequest;
-	struct socket *NewSock;
-	int count = 0;
-	int error;
-
-	EnterFunction("AcceptConnections");
-	
-	if (atomic_read(&ConnectCount)>sysctl_khttpd_maxconnect)
-	{
-		LeaveFunction("AcceptConnections - to many active connections");
-		return 0;
-	}
-	
-	if (Socket==NULL) return 0;
-	
-	tp = tcp_sk(Socket->sk);
-	/* 
-	   Quick test to see if there are connections on the queue.
-	   This is cheaper than accept() itself because this saves us
-	   the allocation of a new socket. (Which doesn't seem to be 
-	   used anyway)
-	*/
-   	if (tp->accept_queue==NULL)
-	{
-		return 0;
-	}
-	
-	error = 0;	
-	while (error>=0)
-	{
-		NewSock = sock_alloc();
-		if (NewSock==NULL)
-			break;
-			
-			
-		NewSock->type = Socket->type;
-		NewSock->ops = Socket->ops;
-		
-		
-		error = Socket->ops->accept(Socket,NewSock,O_NONBLOCK);
-		
-
-		if (error<0)
-		{
-			sock_release(NewSock);
-			break;
-		}
-
-		if (NewSock->sk->state==TCP_CLOSE)
-		{
-			sock_release(NewSock);
-			continue;
-		}
-		
-		/* Allocate a request-entry for the connection */
-		NewRequest = kmalloc(sizeof(struct http_request),(int)GFP_KERNEL); 
-		
-		if (NewRequest == NULL)
-		{
-			Send50x(NewSock); 	/* Service not available. Try again later */
-			sock_release(NewSock);
-			break;
-		}
-		memset(NewRequest,0,sizeof(struct http_request));  
-		
-		NewRequest->sock = NewSock;
-		
-		NewRequest->Next = threadinfo[CPUNR].WaitForHeaderQueue;
-		
-		init_waitqueue_entry(&NewRequest->sleep,current);
-		
-		add_wait_queue(NewSock->sk->sleep,&(NewRequest->sleep));
-		
-		threadinfo[CPUNR].WaitForHeaderQueue = NewRequest;
-		
-		atomic_inc(&ConnectCount);
-
-	
-		count++;
-	}		
-	
-	LeaveFunction("AcceptConnections");
-	return count;
-}
diff -Nru a/net/khttpd/datasending.c b/net/khttpd/datasending.c
--- a/net/khttpd/datasending.c	Thu Aug  1 14:17:39 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,242 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Send actual file-data to the connections
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-/*
-
-Purpose:
-
-DataSending does the actual sending of file-data to the socket.
-
-Note: Since asynchronous reads do not -yet- exists, this might block!
-
-Return value:
-	The number of requests that changed status (ie: made some progress)
-*/
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-
-#include <net/tcp.h>
-
-#include <asm/uaccess.h>
-#include <linux/smp_lock.h>
-
-#include "structure.h"
-#include "prototypes.h"
-
-static	char	*Block[CONFIG_KHTTPD_NUMCPU];
-
-/*
-
-This send_actor is for use with do_generic_file_read (ie sendfile())
-It sends the data to the socket indicated by desc->buf.
-
-*/
-static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
-{
-	int written;
-	char *kaddr;
-	unsigned long count = desc->count;
-	struct socket *sock = (struct socket *) desc->buf;
-	mm_segment_t old_fs;
-
-	if (size > count)
-		size = count;
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	kaddr = kmap(page);
-	written = SendBuffer_async(sock, kaddr + offset, size);
-	kunmap(page);
-	set_fs(old_fs);
-	if (written < 0) {
-		desc->error = written;
-		written = 0;
-	}
-	desc->count = count - written;
-	desc->written += written;
-	return written;
-}
-
-
-
-
-int DataSending(const int CPUNR)
-{
-	struct http_request *CurrentRequest,**Prev;
-	int count = 0;
-	
-	EnterFunction("DataSending");
-	
-	Prev = &(threadinfo[CPUNR].DataSendingQueue);
-	CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
-	while (CurrentRequest!=NULL)
-	{
-		int ReadSize,Space;
-		int retval;
-
-
-		/* First, test if the socket has any buffer-space left.
-		   If not, no need to actually try to send something.  */
-		  
-		
-		Space = sock_wspace(CurrentRequest->sock->sk);
-		
-		ReadSize = min_t(int, 4 * 4096, CurrentRequest->FileLength - CurrentRequest->BytesSent);
-		ReadSize = min_t(int, ReadSize, Space);
-
-		if (ReadSize>0)
-		{			
-			struct inode *inode;
-			
-			inode = CurrentRequest->filp->f_dentry->d_inode;
-			
-			if (inode->i_mapping->a_ops->readpage) {
-				/* This does the actual transfer using sendfile */		
-				read_descriptor_t desc;
-				loff_t *ppos;
-		
-				CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
-
-				ppos = &CurrentRequest->filp->f_pos;
-
-				desc.written = 0;
-				desc.count = ReadSize;
-				desc.buf = (char *) CurrentRequest->sock;
-				desc.error = 0;
-				do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor);
-				if (desc.written>0)
-				{	
-					CurrentRequest->BytesSent += desc.written;
-					count++;
-				}			
-			} 
-			else  /* FS doesn't support sendfile() */
-			{
-				mm_segment_t oldfs;
-				CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
-				
-				oldfs = get_fs(); set_fs(KERNEL_DS);
-				retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
-				set_fs(oldfs);
-		
-				if (retval>0)
-				{
-					retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
-					if (retval>0)
-					{
-						CurrentRequest->BytesSent += retval;
-						count++;				
-					}
-				}
-			}
-		
-		}
-		
-		/* 
-		   If end-of-file or closed connection: Finish this request 
-		   by moving it to the "logging" queue. 
-		*/
-		if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)||
-		    (CurrentRequest->sock->sk->state!=TCP_ESTABLISHED
-		     && CurrentRequest->sock->sk->state!=TCP_CLOSE_WAIT))
-		{
-			struct http_request *Next;
-			Next = CurrentRequest->Next;
-
-			lock_sock(CurrentRequest->sock->sk);
-			if  (CurrentRequest->sock->sk->state == TCP_ESTABLISHED ||
-			     CurrentRequest->sock->sk->state == TCP_CLOSE_WAIT)
-			{
-				struct tcp_opt *tp =
-					       tcp_sk(CurrentRequest->sock->sk);
-				tp->nonagle = 0;
-				tcp_push_pending_frames(CurrentRequest->sock->sk, tp);
-			}
-			release_sock(CurrentRequest->sock->sk);
-
-			(*Prev) = CurrentRequest->Next;
-			
-			CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue;
-			threadinfo[CPUNR].LoggingQueue = CurrentRequest;	
-				
-			CurrentRequest = Next;
-			continue;
-		
-		}
-		
-
-		Prev = &(CurrentRequest->Next);	
-		CurrentRequest = CurrentRequest->Next;
-	}
-	
-	LeaveFunction("DataSending");
-	return count;
-}
-
-int InitDataSending(int ThreadCount)
-{
-	int I,I2;
-	
-	EnterFunction("InitDataSending");
-	I=0;
-	while (I<ThreadCount)
-	{
-		Block[I] = (char*)get_free_page((int)GFP_KERNEL);
-		if (Block[I] == NULL) 
-		{
-			I2=0;
-			while (I2<I-1)
-			{
-				free_page((unsigned long)Block[I2++]);
-			}
-			LeaveFunction("InitDataSending - abort");
-			return -1;
-		}
-		I++;
-	}
-	LeaveFunction("InitDataSending");
-	return 0;		
-}
-
-void StopDataSending(const int CPUNR)
-{
-	struct http_request *CurrentRequest,*Next;
-	
-	EnterFunction("StopDataSending");
-	CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
-
-	while (CurrentRequest!=NULL)
-	{	
-		Next = CurrentRequest->Next;
-		CleanUpRequest(CurrentRequest);
-		CurrentRequest=Next;		
-	}
-	
-	threadinfo[CPUNR].DataSendingQueue = NULL;
-
-	free_page( (unsigned long)Block[CPUNR]);
-	LeaveFunction("StopDataSending");
-}
diff -Nru a/net/khttpd/logging.c b/net/khttpd/logging.c
--- a/net/khttpd/logging.c	Thu Aug  1 14:17:37 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,95 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-logging.c takes care of shutting down a connection.
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/smp_lock.h>
-#include <net/tcp.h>
-#include <asm/uaccess.h>
-#include "structure.h"
-#include "prototypes.h"
-
-/*
-
-Purpose:
-
-Logging() terminates "finished" connections and will eventually log them to a 
-userspace daemon.
-
-Return value:
-	The number of requests that changed status, thus the number of connections
-	that shut down.
-*/
-
-
-int Logging(const int CPUNR)
-{
-	struct http_request *CurrentRequest,*Req;
-	int count = 0;
-	
-	EnterFunction("Logging");
-	
-	CurrentRequest = threadinfo[CPUNR].LoggingQueue;
-	
-	/* For now, all requests are removed immediatly, but this changes
-	   when userspace-logging is added. */
-	   
-	while (CurrentRequest!=NULL)
-	{
-
-		Req = CurrentRequest->Next;
-
-		CleanUpRequest(CurrentRequest);
-		
-		threadinfo[CPUNR].LoggingQueue = Req;
-			
-		CurrentRequest = Req;
-	
-		count++;
-		
-	}
-	
-	LeaveFunction("Logging");
-	return count;
-}
-
-
-
-void StopLogging(const int CPUNR)
-{
-	struct http_request *CurrentRequest,*Next;
-	
-	EnterFunction("StopLogging");
-	CurrentRequest = threadinfo[CPUNR].LoggingQueue;
-	
-	while (CurrentRequest!=NULL)
-	{
-		Next=CurrentRequest->Next;
-		CleanUpRequest(CurrentRequest);
-		CurrentRequest=Next;		
-	}
-	
-	threadinfo[CPUNR].LoggingQueue = NULL;
-	LeaveFunction("StopLogging");
-}
diff -Nru a/net/khttpd/main.c b/net/khttpd/main.c
--- a/net/khttpd/main.c	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,394 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Main program
-
-
-kHTTPd TNG consists of 1 thread, this main-thread handles ALL connections
-simultanious. It does this by keeping queues with the requests in different
-stages.
-
-The stages are
-
-<not accepted> 		-	TCP/IP connection is not accepted yet
-WaitForHeaders		-	Connection is accepted, waiting for headers
-DataSending		-	Headers decoded, sending file-data
-Userspace		-	Requires userspace daemon 
-Logging			-	The request is finished, cleanup and logging
-
-A typical flow for a request would be:
-
-<not accepted>
-WaitForHeaders
-DataSending
-Logging
-
-or
-
-<not accepted>
-WaitForHeaders
-Userspace
-
-
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-
-static int errno;
-#define __KERNEL_SYSCALLS__
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/init.h>
-#include <linux/wait.h>
-#include <linux/smp_lock.h>
-#include <asm/unistd.h>
-
-#include "structure.h"
-#include "prototypes.h"
-#include "sysctl.h"
-
-struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU];  /* The actual work-queues */
-
-
-atomic_t	ConnectCount;
-atomic_t	DaemonCount;
-
-static int	ActualThreads; /* The number of actual, active threads */
-
-
-static int ConnectionsPending(int CPUNR)
-{
-	if (threadinfo[CPUNR].DataSendingQueue!=NULL) return O_NONBLOCK;
-	if (threadinfo[CPUNR].WaitForHeaderQueue!=NULL) return O_NONBLOCK;
-	if (threadinfo[CPUNR].LoggingQueue!=NULL) return O_NONBLOCK;
-	if (threadinfo[CPUNR].UserspaceQueue!=NULL) return O_NONBLOCK;
-  return 0;
-}
-
-
-
-static wait_queue_head_t DummyWQ[CONFIG_KHTTPD_NUMCPU];
-static atomic_t Running[CONFIG_KHTTPD_NUMCPU]; 
-
-static int MainDaemon(void *cpu_pointer)
-{
-	int CPUNR;
-	sigset_t tmpsig;
-	
-	DECLARE_WAITQUEUE(main_wait,current);
-	
-	MOD_INC_USE_COUNT;
-
-	
-	CPUNR=0;
-	if (cpu_pointer!=NULL)
-	CPUNR=(int)*(int*)cpu_pointer;
-
-	sprintf(current->comm,"khttpd - %i",CPUNR);
-	daemonize();
-	
-	init_waitqueue_head(&(DummyWQ[CPUNR]));
-	
-
-	/* Block all signals except SIGKILL, SIGSTOP and SIGHUP */
-	spin_lock_irq(&current->sigmask_lock);
-	tmpsig = current->blocked;
-	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP)| sigmask(SIGHUP));
-	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
-	
-	
-	if (MainSocket->sk==NULL)
-	 	return 0;
-	add_wait_queue_exclusive(MainSocket->sk->sleep,&(main_wait));
-	atomic_inc(&DaemonCount);
-	atomic_set(&Running[CPUNR],1);
-	
-	while (sysctl_khttpd_stop==0)
-	{
-		int changes = 0;
-				
-
-		
-		changes +=AcceptConnections(CPUNR,MainSocket);
-		if (ConnectionsPending(CPUNR))
-		{
-			changes +=WaitForHeaders(CPUNR);
-			changes +=DataSending(CPUNR);
-			changes +=Userspace(CPUNR);
-			changes +=Logging(CPUNR);
-			/* Test for incoming connections _again_, because it is possible
-			   one came in during the other steps, and the wakeup doesn't happen
-			   then.
-			*/
-			changes +=AcceptConnections(CPUNR,MainSocket);
-		}
-		
-		if (changes==0) 
-		{
-			(void)interruptible_sleep_on_timeout(&(DummyWQ[CPUNR]),1);	
-			if (CPUNR==0) 
-				UpdateCurrentDate();
-		}
-			
-		if (signal_pending(current)!=0)
-		{
-			(void)printk(KERN_NOTICE "kHTTPd: Ring Ring - signal received\n");
-			break;		  
-		}
-	
-	}
-	
-	remove_wait_queue(MainSocket->sk->sleep,&(main_wait));
-	
-	StopWaitingForHeaders(CPUNR);
-	StopDataSending(CPUNR);
-	StopUserspace(CPUNR);
-	StopLogging(CPUNR);
-	
-	atomic_set(&Running[CPUNR],0);
-	atomic_dec(&DaemonCount);
-	(void)printk(KERN_NOTICE "kHTTPd: Daemon %i has ended\n",CPUNR);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-static int CountBuf[CONFIG_KHTTPD_NUMCPU];
-
-
-
-/*
-
-The ManagementDaemon has a very simple task: Start the real daemons when the user wants us
-to, and cleanup when the users wants to unload the module.
-
-Initially, kHTTPd didn't have this thread, but it is the only way to have "delayed activation",
-a feature required to prevent accidental activations resulting in unexpected backdoors.
-
-*/
-static int ManagementDaemon(void *unused)
-{
-	sigset_t tmpsig;
-	int waitpid_result;
-	
-	DECLARE_WAIT_QUEUE_HEAD(WQ);
-	
-	
-	sprintf(current->comm,"khttpd manager");
-	daemonize();
-	
-
-	/* Block all signals except SIGKILL and SIGSTOP */
-	spin_lock_irq(&current->sigmask_lock);
-	tmpsig = current->blocked;
-	siginitsetinv(&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) );
-	recalc_sigpending();
-	spin_unlock_irq(&current->sigmask_lock);
-
-
-	/* main loop */
-	while (sysctl_khttpd_unload==0)
-	{
-		int I;
-		
-		
-		/* First : wait for activation */
-		
-		sysctl_khttpd_start = 0;
-		
-		while ( (sysctl_khttpd_start==0) && (!signal_pending(current)) && (sysctl_khttpd_unload==0) )
-		{
-			current->state = TASK_INTERRUPTIBLE;
-			interruptible_sleep_on_timeout(&WQ,HZ); 
-		}
-		
-		if ( (signal_pending(current)) || (sysctl_khttpd_unload!=0) )
-		 	break;
-		 	
-		/* Then start listening and spawn the daemons */
-		 	
-		if (StartListening(sysctl_khttpd_serverport)==0)
-		{
-			continue;
-		}
-		
-		ActualThreads = sysctl_khttpd_threads;
-		if (ActualThreads<1) 
-			ActualThreads = 1;
-			
-		if (ActualThreads>CONFIG_KHTTPD_NUMCPU) 
-			ActualThreads = CONFIG_KHTTPD_NUMCPU;
-		
-		/* Write back the actual value */
-		
-		sysctl_khttpd_threads = ActualThreads;
-		
-		InitUserspace(ActualThreads);
-		
-		if (InitDataSending(ActualThreads)!=0)
-		{
-			StopListening();
-			continue;
-		}
-		if (InitWaitHeaders(ActualThreads)!=0)
-		{
-			I=0;
-			while (I<ActualThreads)
-			{
-				StopDataSending(I);
-				I++;
-			}
-			StopListening();
-			continue;
-		}
-	
-		/* Clean all queues */
-		memset(threadinfo, 0, sizeof(struct khttpd_threadinfo));
-
-
-		 	
-		I=0;
-		while (I<ActualThreads)
-		{
-			atomic_set(&Running[I],1);
-			(void)kernel_thread(MainDaemon,&(CountBuf[I]), CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-			I++;
-		}
-		
-		/* Then wait for deactivation */
-		sysctl_khttpd_stop = 0;
-
-		while ( (sysctl_khttpd_stop==0) && (!signal_pending(current)) && (sysctl_khttpd_unload==0) )
-		{
-			if (atomic_read(&DaemonCount)<ActualThreads)
-			{
-				I=0;
-				while (I<ActualThreads)
-				{
-					if (atomic_read(&Running[I])==0)
-					{
-						atomic_set(&Running[I],1);
-						(void)kernel_thread(MainDaemon,&(CountBuf[I]), CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-						(void)printk(KERN_CRIT "kHTTPd: Restarting daemon %i \n",I);
-					}
-					I++;
-				}
-			}
-			interruptible_sleep_on_timeout(&WQ,HZ);
-			
-			/* reap the daemons */
-			waitpid_result = waitpid(-1,NULL,__WCLONE|WNOHANG);
-			
-		}
-		
-		
-		/* The user wants us to stop. So stop listening on the socket. */
-		if (sysctl_khttpd_stop!=0)	
-		{
-			/* Wait for the daemons to stop, one second per iteration */
-			while (atomic_read(&DaemonCount)>0)
-		 		interruptible_sleep_on_timeout(&WQ,HZ);
-			StopListening();
-		}
-
-		
-	
-	}
-	
-	sysctl_khttpd_stop = 1;
-
-	/* Wait for the daemons to stop, one second per iteration */
-	while (atomic_read(&DaemonCount)>0)
- 		interruptible_sleep_on_timeout(&WQ,HZ);
-		
-		
-	waitpid_result = 1;
-	/* reap the zombie-daemons */
-	while (waitpid_result>0)
-		waitpid_result = waitpid(-1,NULL,__WCLONE|WNOHANG);
-		
-	StopListening();
-	
-	
-	(void)printk(KERN_NOTICE "kHTTPd: Management daemon stopped. \n        You can unload the module now.\n");
-
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-int __init khttpd_init(void)
-{
-	int I;
-
-	MOD_INC_USE_COUNT;
-	
-	I=0;
-	while (I<CONFIG_KHTTPD_NUMCPU)
-	{
-		CountBuf[I]=I;
-		
-		I++;
-	}
-	
-	atomic_set(&ConnectCount,0);
-	atomic_set(&DaemonCount,0);
-	
-
-	/* Maybe the mime-types will be set-able through sysctl in the future */	   
-		
- 	AddMimeType(".htm","text/html");
- 	AddMimeType("html","text/html");
- 	AddMimeType(".gif","image/gif");
- 	AddMimeType(".jpg","image/jpeg");
- 	AddMimeType(".png","image/png");
- 	AddMimeType("tiff","image/tiff");
- 	AddMimeType(".zip","application/zip");
-	AddMimeType(".pdf","application/pdf");
- 	AddMimeType("r.gz","application/x-gtar");
- 	AddMimeType(".tgz","application/x-gtar");
-	AddMimeType(".deb","application/x-debian-package");
-	AddMimeType("lass","application/x-java");
-	AddMimeType(".mp3","audio/mpeg");
-	AddMimeType(".txt","text/plain");
-	
-	AddDynamicString("..");
-	AddDynamicString("cgi-bin");
-
-	StartSysctl();
-	
-	(void)kernel_thread(ManagementDaemon,NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
-	
-	return 0;
-}
-
-void khttpd_cleanup(void)
-{
-	EndSysctl();
-}
-
-	module_init(khttpd_init)
-	module_exit(khttpd_cleanup)
-
-MODULE_LICENSE("GPL");
diff -Nru a/net/khttpd/make_times_h.c b/net/khttpd/make_times_h.c
--- a/net/khttpd/make_times_h.c	Thu Aug  1 14:17:39 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,115 +0,0 @@
-/*
-
-This program generates the "times.h" file with the zulu-times of the first of
-every month of a decade.
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-#include <time.h>
-#include <stdio.h>
-
-static time_t GetDay(int D,int M,int Y)
-{
-	struct tm TM;
-	
-	TM.tm_sec    	= 0;
-	TM.tm_min	= 0;
-	TM.tm_hour	= 0;
-	TM.tm_mday	= D;
-	TM.tm_mon	= M;
-	TM.tm_wday	= 0;
-	TM.tm_yday	= 0;
-	TM.tm_year	= Y-1900;
-	TM.tm_isdst	= 0;
-	
-	return mktime(&TM);
-	
-}
-static int WeekGetDay(int D,int M,int Y)
-{
-	struct tm TM;
-	
-	TM.tm_sec    	= 0;
-	TM.tm_min	= 0;
-	TM.tm_hour	= 0;
-	TM.tm_mday	= D;
-	TM.tm_mon	= M;
-	TM.tm_year	= Y-1900;
-	TM.tm_isdst	= 0;
-	TM.tm_wday	= 0;
-	TM.tm_yday	= 0;
-	
-	(void)mktime(&TM);
-	
-	return TM.tm_wday;
-	
-}
-
-int main(void)
-{
-	int M,Y;
-
-	printf("static time_t TimeDays[10][13] = { \n");
-	
-	Y=1997;
-	while (Y<2007)
-	{
-		M=0;
-		printf(" { ");
-		while (M<12)
-		{
-			printf("%i",(int)GetDay(1,M,Y));
-     		  	printf(",\t");
-		
-			M++;
-		}
-		
-		printf("%i } ",(int)GetDay(1,0,Y+1));
-		if (Y!=2006) printf(",");
-		printf("\n");
-		Y++;
-	}
-	printf("};\n");
-
-	printf("static int WeekDays[10][13] = { \n");
-	
-	Y=1997;
-	while (Y<2007)
-	{
-		M=0;
-		printf(" { ");
-		while (M<12)
-		{
-			printf("%i",(int)WeekGetDay(1,M,Y));
-     		  	printf(",\t");
-		
-			M++;
-		}
-		
-		printf("%i } ",(int)WeekGetDay(1,0,Y+1));
-		if (Y!=2006) printf(",");
-		printf("\n");
-		Y++;
-	}
-	printf("};\n");
-	printf("#define KHTTPD_YEAROFFSET   1997\n");
-	printf("#define KHTTPD_NUMYEARS     10\n");
-	
-	return 0;
-}
diff -Nru a/net/khttpd/misc.c b/net/khttpd/misc.c
--- a/net/khttpd/misc.c	Thu Aug  1 14:17:40 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,242 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-General functions
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-#include <linux/kernel.h>
-
-#include <linux/ctype.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/unistd.h>
-#include <linux/file.h>
-#include <linux/smp_lock.h>
-
-#include <net/ip.h>
-#include <net/sock.h>
-
-#include <asm/atomic.h>
-#include <asm/errno.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-#include "structure.h"
-#include "prototypes.h"
-
-#ifndef ECONNRESET
-#define ECONNRESET 102
-#endif
-
-
-/*
-
-Readrest reads and discards all pending input on a socket. This is required
-before closing the socket.
-
-*/
-static void ReadRest(struct socket *sock)
-{
-	struct msghdr		msg;
-	struct iovec		iov;
-	int			len;
-
-	mm_segment_t		oldfs;
-	
-	
-	EnterFunction("ReadRest");
-	
-	
-	if (sock->sk==NULL)
-		return;
-
-	len = 1;
-		
-	while (len>0)
-	{
-		static char		Buffer[1024];   /* Never read, so doesn't need to
-							   be SMP safe */
-
-		msg.msg_name     = 0;
-		msg.msg_namelen  = 0;
-		msg.msg_iov	 = &iov;
-		msg.msg_iovlen   = 1;
-		msg.msg_control  = NULL;
-		msg.msg_controllen = 0;
-		msg.msg_flags    = MSG_DONTWAIT;
-	
-		msg.msg_iov->iov_base = &Buffer[0];
-		msg.msg_iov->iov_len  = (__kernel_size_t)1024;
-	
-		len = 0;
-		oldfs = get_fs(); set_fs(KERNEL_DS);
-		len = sock_recvmsg(sock,&msg,1024,MSG_DONTWAIT);
-		set_fs(oldfs);
-	}
-	LeaveFunction("ReadRest");
-}
-
-
-/*
-
-CleanUpRequest takes care of shutting down the connection, closing the file-pointer
-and releasing the memory of the request-structure. Do not try to access it afterwards!
-
-*/
-void CleanUpRequest(struct http_request *Req)
-{
-	EnterFunction("CleanUpRequest");	
-	
-	/* Close the socket ....*/
-	if ((Req->sock!=NULL)&&(Req->sock->sk!=NULL))
-	{
-		ReadRest(Req->sock);
-		remove_wait_queue(Req->sock->sk->sleep,&(Req->sleep));
-	    	sock_release(Req->sock);
-	}
-	
-	/* ... and the file-pointer ... */
-	if (Req->filp!=NULL)
-	{
-	    	fput(Req->filp);
-	    	Req->filp = NULL;
-	}
-	
-	
-	/* ... and release the memory for the structure. */
-	kfree(Req);
-	
-	atomic_dec(&ConnectCount);
-	LeaveFunction("CleanUpRequest");
-}
-
-
-/*
-
-SendBuffer and Sendbuffer_async send "Length" bytes from "Buffer" to the "sock"et.
-The _async-version is non-blocking.
-
-A positive return-value indicates the number of bytes sent, a negative value indicates
-an error-condition.
-
-*/
-int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length)
-{
-	struct msghdr	msg;
-	mm_segment_t	oldfs;
-	struct iovec	iov;
-	int 		len;
-	
-	EnterFunction("SendBuffer");
-	
-	msg.msg_name     = 0;
-	msg.msg_namelen  = 0;
-	msg.msg_iov	 = &iov;
-	msg.msg_iovlen   = 1;
-	msg.msg_control  = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags    = MSG_NOSIGNAL;    
-	msg.msg_iov->iov_len = (__kernel_size_t)Length;
-	msg.msg_iov->iov_base = (char*) Buffer;
-	
-	
-	len = 0;
-	
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	len = sock_sendmsg(sock,&msg,(size_t)(Length-len));
-	set_fs(oldfs);
-	LeaveFunction("SendBuffer");
-	return len;	
-}
-
-int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length)
-{
-	struct msghdr	msg;
-	mm_segment_t	oldfs;
-	struct iovec	iov;
-	int 		len;
-	
-	EnterFunction("SendBuffer_async");
-	msg.msg_name     = 0;
-	msg.msg_namelen  = 0;
-	msg.msg_iov	 = &iov;
-	msg.msg_iovlen   = 1;
-	msg.msg_control  = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags    = MSG_DONTWAIT|MSG_NOSIGNAL;    
-	msg.msg_iov->iov_base = (char*) Buffer;
-	msg.msg_iov->iov_len  = (__kernel_size_t)Length;
-	
-
-	if (sock->sk)
-	{	
-		oldfs = get_fs(); set_fs(KERNEL_DS);
-		len = sock_sendmsg(sock,&msg,(size_t)(Length));
-		set_fs(oldfs);
-	} else
-	{
-		return -ECONNRESET;
-	}
-	
-	LeaveFunction("SendBuffer_async");
-	return len;	
-}
-
-
-
-
-/* 
-
-HTTP header shortcuts. Hardcoded since these might be called in a low-memory
-situation, and they don't change anyhow.
-
-*/
-
-static char NoPerm[] = "HTTP/1.0 403 Forbidden\r\nServer: kHTTPd 0.1.6\r\n\r\n";
-static char TryLater[] = "HTTP/1.0 503 Service Unavailable\r\nServer: kHTTPd 0.1.6\r\nContent-Length: 15\r\n\r\nTry again later";
-static char NotModified[] = "HTTP/1.0 304 Not Modified\r\nServer: kHTTPd 0.1.6\r\n\r\n";
-
-
-void Send403(struct socket *sock)
-{
-	EnterFunction("Send403");
-	(void)SendBuffer(sock,NoPerm,strlen(NoPerm));
-	LeaveFunction("Send403");
-}
-
-void Send304(struct socket *sock)
-{
-	EnterFunction("Send304");
-	(void)SendBuffer(sock,NotModified,strlen(NotModified));
-	LeaveFunction("Send304");
-}
-
-void Send50x(struct socket *sock)
-{
-	EnterFunction("Send50x");
-	(void)SendBuffer(sock,TryLater,strlen(TryLater));
-	LeaveFunction("Send50x");
-}
-
diff -Nru a/net/khttpd/prototypes.h b/net/khttpd/prototypes.h
--- a/net/khttpd/prototypes.h	Thu Aug  1 14:17:41 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,121 +0,0 @@
-#ifndef _INCLUDE_GUARD_PROTOTYPES_H
-#define _INCLUDE_GUARD_PROTOTYPES_H
-
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/net.h>
-#include <linux/time.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-#include <asm/uaccess.h>
-
-#include "structure.h"
-
-
-/* General defines and stuff */
-
-
-#define CONFIG_KHTTPD_NUMCPU 16    /* Maximum number of threads */
-
-#ifdef OOPSTRACE
-#define EnterFunction(x)   printk("Enter: %s, %s line %i\n",x,__FILE__,__LINE__)
-#define LeaveFunction(x)   printk("Leave: %s, %s line %i\n",x,__FILE__,__LINE__)
-#else
-#define EnterFunction(x)   do {} while (0)
-#define LeaveFunction(x)   do {} while (0)
-#endif
-
-
-
-/* sockets.c */
-int  StartListening(const int Port);
-void StopListening(void);
-
-extern struct socket *MainSocket;
-
-
-/* sysctl.c */
-void StartSysctl(void);
-void EndSysctl(void);
-
-extern int sysctl_khttpd_stop;
-
-
-/* main.c */
-
-
-extern struct khttpd_threadinfo threadinfo[CONFIG_KHTTPD_NUMCPU];
-extern char CurrentTime[];
-extern atomic_t ConnectCount;
-extern struct wait_queue main_wait[CONFIG_KHTTPD_NUMCPU];
-
-/* misc.c */
-
-void CleanUpRequest(struct http_request *Req);
-int SendBuffer(struct socket *sock, const char *Buffer,const size_t Length);
-int SendBuffer_async(struct socket *sock, const char *Buffer,const size_t Length);
-void Send403(struct socket *sock);
-void Send304(struct socket *sock);
-void Send50x(struct socket *sock);
-
-/* accept.c */
-
-int AcceptConnections(const int CPUNR,struct socket *Socket);
-
-/* waitheaders.c */
-
-int WaitForHeaders(const int CPUNR);
-void StopWaitingForHeaders(const int CPUNR);
-int InitWaitHeaders(int ThreadCount);
-
-/* datasending.c */
-
-int DataSending(const int CPUNR);
-void StopDataSending(const int CPUNR);
-int InitDataSending(int ThreadCount);
-
-
-/* userspace.c */
-
-int Userspace(const int CPUNR);
-void StopUserspace(const int CPUNR);
-void InitUserspace(const int CPUNR);
-
-
-/* rfc_time.c */
-
-void time_Unix2RFC(const time_t Zulu,char *Buffer);
-void UpdateCurrentDate(void);
-time_t mimeTime_to_UnixTime(char *Q);
-extern int CurrentTime_i;
-
-/* rfc.c */
-
-void ParseHeader(char *Buffer,const int length, struct http_request *Head);
-char *ResolveMimeType(const char *File,__kernel_size_t *Len);
-void AddMimeType(const char *Ident,const char *Type);
-void SendHTTPHeader(struct http_request *Request);
-
-
-
-/* security.c */
-
-struct file *OpenFileForSecurity(char *Filename);
-void AddDynamicString(const char *String);
-void GetSecureString(char *String);
-
-
-/* logging.c */
-
-int Logging(const int CPUNR);
-void StopLogging(const int CPUNR);
-
-
-/* Other prototypes */
-
-
-
-#endif
diff -Nru a/net/khttpd/rfc.c b/net/khttpd/rfc.c
--- a/net/khttpd/rfc.c	Thu Aug  1 14:17:40 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,374 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-RFC related functions (headers and stuff)
-
-*/
-
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-
-#include <linux/kernel.h>
-
-#include <linux/ctype.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/unistd.h>
-#include <linux/file.h>
-#include <linux/smp_lock.h>
-
-#include <net/ip.h>
-#include <net/sock.h>
-
-#include <asm/atomic.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-
-#include "prototypes.h"
-#include "structure.h"
-#include "sysctl.h"
-
-
-#define KHTTPD_NUMMIMETYPES 	40
-
-static atomic_t	MimeCount;
-
-struct MimeType
-{
-	__u32 	identifier;
-	char	type[64-sizeof(__u32)-sizeof(__kernel_size_t)];  
-	__kernel_size_t	len;
-};
-
-static struct MimeType	MimeTypes[KHTTPD_NUMMIMETYPES];
-
-
-void AddMimeType(const char *Ident,const char *Type)
-{	
-	__u32	*I;
-	
-	EnterFunction("AddMimeType");
-	
-	if (strlen(Ident)!=4) 
-   	{	
-   		(void)printk(KERN_ERR "httpd: Only 4-byte mime-identifiers are accepted\n");
-   		return;
-   	}
-
-	if (strlen(Type)>(64-sizeof(__u32)-sizeof(__kernel_size_t) ) )  
-   	{	
-   		(void)printk(KERN_ERR "httpd: Mime-string too long.\n");
-   		return;
-   	}
-   	
-   	I=(__u32*)Ident;
-   	
-   	/* FIXME: Need to lock-down all access to the mime-structure here */
-   	/*        For now, just don't add mime-types after initialisation */
-   	
-   	
-   	MimeTypes[atomic_read(&MimeCount)].identifier=*I;
-   	strncpy(MimeTypes[atomic_read(&MimeCount)].type,Type,(64-sizeof(__u32)-sizeof(__kernel_size_t)));
-   	MimeTypes[atomic_read(&MimeCount)].len = strlen(Type);
-   	
-   	atomic_inc(&MimeCount);
-   	LeaveFunction("AddMimeType");
-}
-
-
-char *ResolveMimeType(const char *File,__kernel_size_t *Len)
-/*
-
-	The returned string is for READ ONLY, ownership of the memory is NOT
-	transferred.
-
-*/
-{	
-	__u32	*I;
-	int pos,lc,filelen;
-	
-	EnterFunction("ResolveMimeType");
-	
-	*Len = 0;
-	
-	if (File==NULL)
-		return NULL;
-	
-	filelen = (int)strlen(File);
-	
-	if (filelen<4) 
-   	{	
-   		return NULL;
-   	}
-   	
-   	/* The Merced-people are NOT going to like this! So this has to be fixed
-   	   in a later stage. */
-
-	pos = filelen-4;
-   	I=(__u32*)(File+pos);
-   	
-   	lc=0;
-   	
-   	while (lc<atomic_read(&MimeCount))
- 	{
-   		if (MimeTypes[lc].identifier == *I)
-   		{
-   			*Len = MimeTypes[lc].len;
-   			LeaveFunction("ResolveMimeType - success");
-   	  		return MimeTypes[lc].type;
-   	  	}
-   	  	lc++;
-   	} 	
-   	
-	if (sysctl_khttpd_sloppymime)
-	{
-		*Len = MimeTypes[0].len;  
-		LeaveFunction("ResolveMimeType - unknown");
-	   	return MimeTypes[0].type;
-	}
-	else
-	{
-		LeaveFunction("ResolveMimeType - failure");
-	   	return NULL;
-	}
-}
-
-
-static char HeaderPart1[] = "HTTP/1.0 200 OK\r\nServer: kHTTPd/0.1.6\r\nDate: ";
-#ifdef BENCHMARK
-static char HeaderPart1b[] ="HTTP/1.0 200 OK";
-#endif
-static char HeaderPart3[] = "\r\nContent-type: ";
-static char HeaderPart5[] = "\r\nLast-modified: ";
-static char HeaderPart7[] = "\r\nContent-length: ";
-static char HeaderPart9[] = "\r\n\r\n";
-
-#ifdef BENCHMARK
-/* In BENCHMARK-mode, just send the bare essentials */
-void SendHTTPHeader(struct http_request *Request)
-{
-	struct msghdr	msg;
-	mm_segment_t	oldfs;
-	struct iovec	iov[9];
-	int 		len,len2;
-	
-	
-	EnterFunction("SendHTTPHeader");
-		
-	msg.msg_name     = 0;
-	msg.msg_namelen  = 0;
-	msg.msg_iov	 = &iov[0];
-	msg.msg_iovlen   = 6;
-	msg.msg_control  = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags    = 0;  /* Synchronous for now */
-	
-	iov[0].iov_base = HeaderPart1b;
-	iov[0].iov_len  = 15;
-	iov[1].iov_base = HeaderPart3;
-	iov[1].iov_len  = 16;
-	iov[2].iov_base = Request->MimeType;
-	iov[2].iov_len  = Request->MimeLength;
-	
-	iov[3].iov_base = HeaderPart7;
-	iov[3].iov_len  = 18;
-	
-	
-	sprintf(Request->LengthS,"%i",Request->FileLength);
-	iov[4].iov_base = Request->LengthS;
-	iov[4].iov_len  = strlen(Request->LengthS);
-	iov[5].iov_base = HeaderPart9;
-	iov[5].iov_len  = 4;
-	
-	len2=15+16+18+iov[2].iov_len+iov[4].iov_len+4;
-	
-	
-	len = 0;
-	
-
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	len = sock_sendmsg(Request->sock,&msg,len2);
-	set_fs(oldfs);
-
-	
-	return;	
-}
-#else
-void SendHTTPHeader(struct http_request *Request)
-{
-	struct msghdr	msg;
-	mm_segment_t	oldfs;
-	struct iovec	iov[9];
-	int 		len,len2;
-	__kernel_size_t	slen;
-	
-	EnterFunction("SendHTTPHeader");
-	
-	msg.msg_name     = 0;
-	msg.msg_namelen  = 0;
-	msg.msg_iov	 = &(iov[0]);
-	msg.msg_iovlen   = 9;
-	msg.msg_control  = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags    = 0;  /* Synchronous for now */
-	
-	iov[0].iov_base = HeaderPart1;
-	iov[0].iov_len  = 45;
-	iov[1].iov_base = CurrentTime;
-	iov[1].iov_len  = 29;
-	iov[2].iov_base = HeaderPart3;
-	iov[2].iov_len  = 16;
-	
-	iov[3].iov_base = Request->MimeType;
-	iov[3].iov_len  = Request->MimeLength;
-	
-	iov[4].iov_base = HeaderPart5;
-	iov[4].iov_len  = 17;
-	iov[5].iov_base = &(Request->TimeS[0]);
-	iov[5].iov_len  = 29;
-	iov[6].iov_base = HeaderPart7;
-	iov[6].iov_len  = 18;
-	iov[7].iov_base = &(Request->LengthS[0]);
-	slen = strlen(Request->LengthS); 
-	iov[7].iov_len  = slen;
-	iov[8].iov_base = HeaderPart9;
-	iov[8].iov_len  = 4;
-	
-	len2=45+2*29+16+17+18+slen+4+iov[3].iov_len;
-	
-	len = 0;
-
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	len = sock_sendmsg(Request->sock,&msg,len2);
-	set_fs(oldfs);
-	LeaveFunction("SendHTTPHeader");
-	
-
-	return;	
-}
-#endif
-
-
-
-/* 
-
-Parse a HTTP-header. Be careful for buffer-overflows here, this is the most important
-place for this, since the remote-user controls the data.
-
-*/
-void ParseHeader(char *Buffer,const int length, struct http_request *Head)
-{
-	char *Endval,*EOL,*tmp;
-	
-	EnterFunction("ParseHeader");
-	Endval = Buffer + length;
-	
-	/* We want to parse only the first header if multiple headers are present */
-	tmp = strstr(Buffer,"\r\n\r\n"); 
-	if (tmp!=NULL)
-	    Endval = tmp;
-	
-	
-	while (Buffer<Endval)
-	{
-		if (isspace(Buffer[0]))
-		{
-			Buffer++;
-			continue;
-		}
-			
-		
-		EOL=strchr(Buffer,'\n');
-		
-		if (EOL==NULL) EOL=Endval;
-		
-		if (EOL-Buffer<4) 
-		{
-			Buffer++;
-			continue;
-		}
-		
-		if (strncmp("GET ",Buffer,4)==0)
-		{
-			int PrefixLen;
-			Buffer+=4;
-			
-			tmp=strchr(Buffer,' ');
-			if (tmp==0) 
-			{
-				tmp=EOL-1;
-				Head->HTTPVER = 9;
-			} else
-				Head->HTTPVER = 10;
-			
-			if (tmp>Endval) continue;
-			
-			strncpy(Head->FileName,sysctl_khttpd_docroot,sizeof(Head->FileName));
-			PrefixLen = strlen(sysctl_khttpd_docroot);
-			Head->FileNameLength = min_t(unsigned int, 255, tmp - Buffer + PrefixLen);		
-			
-			strncat(Head->FileName,Buffer,min_t(unsigned int, 255 - PrefixLen, tmp - Buffer));
-					
-			Buffer=EOL+1;	
-#ifdef BENCHMARK
-			break;
-#endif						
-			continue;
-		}
-#ifndef BENCHMARK		
-		if (strncmp("If-Modified-Since: ",Buffer,19)==0)
-		{
-			Buffer+=19;
-			
-			strncpy(Head->IMS,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
-					
-			Buffer=EOL+1;	
-			continue;
-		}
-
-		if (strncmp("User-Agent: ",Buffer,12)==0)
-		{
-			Buffer+=12;
-			
-			strncpy(Head->Agent,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
-					
-			Buffer=EOL+1;	
-			continue;
-		}
-		
-
-		if (strncmp("Host: ",Buffer,6)==0)
-		{
-			Buffer+=6;
-			
-			strncpy(Head->Host,Buffer,min_t(unsigned int, 127,EOL-Buffer-1));
-					
-			Buffer=EOL+1;	
-			continue;
-		}
-#endif		
-		Buffer = EOL+1;  /* Skip line */
-	}
-	LeaveFunction("ParseHeader");
-}
diff -Nru a/net/khttpd/rfc_time.c b/net/khttpd/rfc_time.c
--- a/net/khttpd/rfc_time.c	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,227 +0,0 @@
-/*
-
-Functions related to time:
-
-1) rfc (string) time to unix-time
-2) unix-time to rfc (string) time
-3) current time to rfc (string) time for the "Date:" header
-
-*/
-
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-#include <linux/time.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-
-
-#include "times.h"
-#include "prototypes.h"
-static char *dayName[7] = {
-	"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-static char *monthName[12] = {
-	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-
-char CurrentTime[64];
-int  CurrentTime_i;
-
-
-static char itoa_h[60]={'0','0','0','0','0','0','0','0','0','0',
-		 '1','1','1','1','1','1','1','1','1','1',
-		 '2','2','2','2','2','2','2','2','2','2',
-		 '3','3','3','3','3','3','3','3','3','3',
-		 '4','4','4','4','4','4','4','4','4','4',
-		 '5','5','5','5','5','5','5','5','5','5'};
-		
-static char itoa_l[60]={'0','1','2','3','4','5','6','7','8','9',
-		 '0','1','2','3','4','5','6','7','8','9',
-		 '0','1','2','3','4','5','6','7','8','9',
-		 '0','1','2','3','4','5','6','7','8','9',
-		 '0','1','2','3','4','5','6','7','8','9',
-		 '0','1','2','3','4','5','6','7','8','9'};
-void time_Unix2RFC(const time_t Zulu,char *Buffer)
-{
-	int Y=0,M=0,D=0;
-	int H=0,Min=0,S=0,WD=0;
-	int I,I2;
-	time_t rest;
-	
-	
-		
-	I=0;
-	while (I<KHTTPD_NUMYEARS)
-	{
-		if (TimeDays[I][0]>Zulu) 
-		   break;
-		I++;
-	}
-	
-	Y=--I;
-	if (I<0) 
-	{
-		Y=0;
-		goto BuildYear;
-	}
-	I2=0;
-	while (I2<=12)
-	{
-		if (TimeDays[I][I2]>Zulu) 
-		   break;
-		I2++;
-	}			   
-	
-	M=I2-1;
-	
-	rest=Zulu - TimeDays[Y][M];
-	WD=WeekDays[Y][M];
-	D=rest/86400;
-	rest=rest%86400;
-	WD+=D;
-	WD=WD%7;
-	H=rest/3600;
-	rest=rest%3600;
-	Min=rest/60;
-	rest=rest%60;
-	S=rest;
-	
-BuildYear:
-	Y+=KHTTPD_YEAROFFSET;
-	
-	
-	/* Format:  Day, 01 Mon 1999 01:01:01 GMT */
-	
-/*	
-	We want to do 
-	
-	sprintf( Buffer, "%s, %02i %s %04i %02i:%02i:%02i GMT",
-		dayName[ WD ], D+1, monthName[ M ], Y,
-		H, Min, S
-	);
-	
-	but this is very expensive. Since the string is fixed length,
-	it is filled manually.
-*/
-	Buffer[0]=dayName[WD][0];
-	Buffer[1]=dayName[WD][1];
-	Buffer[2]=dayName[WD][2];
-	Buffer[3]=',';
-	Buffer[4]=' ';
-	Buffer[5]=itoa_h[D+1];
-	Buffer[6]=itoa_l[D+1];
-	Buffer[7]=' ';
-	Buffer[8]=monthName[M][0];
-	Buffer[9]=monthName[M][1];
-	Buffer[10]=monthName[M][2];
-	Buffer[11]=' ';
-	Buffer[12]=itoa_l[Y/1000];
-	Buffer[13]=itoa_l[(Y/100)%10];
-	Buffer[14]=itoa_l[(Y/10)%10];
-	Buffer[15]=itoa_l[Y%10];
-	Buffer[16]=' ';
-	Buffer[17]=itoa_h[H];
-	Buffer[18]=itoa_l[H];
-	Buffer[19]=':';
-	Buffer[20]=itoa_h[Min];
-	Buffer[21]=itoa_l[Min];
-	Buffer[22]=':';
-	Buffer[23]=itoa_h[S];
-	Buffer[24]=itoa_l[S];
-	Buffer[25]=' ';
-	Buffer[26]='G';
-	Buffer[27]='M';
-	Buffer[28]='T';
-	Buffer[29]=0;
-	
-	
-		
-	
-}
-
-void UpdateCurrentDate(void)
-{
-   struct timeval tv;
-   
-   do_gettimeofday(&tv);
-   if (CurrentTime_i!=tv.tv_sec)
-	   time_Unix2RFC(tv.tv_sec,CurrentTime);
-   
-   CurrentTime_i = tv.tv_sec;
-}
-
-static int MonthHash[32] = {0,0,7,0,0,0,0,0,0,0,0,3,0,0,0,2,6,0,5,0,9,8,4,0,0,11,1,10,0,0,0,0};
-
-#define is_digit(c)	((c) >= '0' && (c) <= '9')
-
-__inline static int skip_atoi(char **s)
-{
-	int i=0;
-
-	while (is_digit(**s))
-		i = i*10 + *((*s)++) - '0';
-	return i;
-}
-
-time_t mimeTime_to_UnixTime(char *Q)
-{
-	int Y,M,D,H,Min,S;
-	unsigned int Hash;
-	time_t Temp;
-	char *s,**s2;
-	
-	s=Q;
-	s2=&s;
-	
-	if (strlen(s)<30) return 0;
-	if (s[3]!=',') return 0;
-	if (s[19]!=':') return 0;
-	
-	s+=5; /* Skip day of week */
-	D = skip_atoi(s2);  /*  Day of month */
-	s++;
-	Hash = (unsigned char)s[0]+(unsigned char)s[2];
-	Hash = (Hash<<1) + (unsigned char)s[1];
-	Hash = (Hash&63)>>1;
-	M = MonthHash[Hash];
-	s+=4;
-	Y = skip_atoi(s2); /* Year */
-	s++;
-	H = skip_atoi(s2); /* Hour */
-	s++;
-	Min = skip_atoi(s2); /* Minutes */
-	s++;
-	S = skip_atoi(s2); /* Seconds */
-	s++;
-	if ((s[0]!='G')||(s[1]!='M')||(s[2]!='T')) 
-	{	
-  		return 0; /* No GMT */
-  	}
-
-	if (Y<KHTTPD_YEAROFFSET) Y = KHTTPD_YEAROFFSET;
-	if (Y>KHTTPD_YEAROFFSET+9) Y = KHTTPD_YEAROFFSET+9;
-	
-	Temp = 	TimeDays[Y-KHTTPD_YEAROFFSET][M];
-	Temp += D*86400+H*3600+Min*60+S;
-	
-	return Temp;  
-}
diff -Nru a/net/khttpd/security.c b/net/khttpd/security.c
--- a/net/khttpd/security.c	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,267 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Permissions/Security functions
-
-*/
-
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-
-#include <linux/kernel.h>
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/smp_lock.h>
-#include <linux/un.h>
-#include <linux/unistd.h>
-
-#include <net/ip.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-
-#include <asm/atomic.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-#include <linux/file.h>
-
-#include "sysctl.h"
-#include "security.h"
-#include "prototypes.h"
-
-/*
-
-The basic security function answers "Userspace" when any one of the following 
-conditions is met:
-
-1) The filename contains a "?" (this is before % decoding, all others are 
-                                after % decoding)
-2) The filename doesn't start with a "/"                                
-3) The file does not exist
-4) The file does not have enough permissions 
-   (sysctl-configurable, default = worldreadble)
-5) The file has any of the "forbidden" permissions 
-   (sysctl-configurable, default = execute, directory and sticky)
-6) The filename contains a string as defined in the "Dynamic" list.
-
-*/	
-
-
-/* Prototypes */
-
-static void DecodeHexChars(char *URL);
-static struct DynamicString *DynamicList=NULL;
-
-	
-
-/*
-
-The function "OpenFileForSecurity" returns either the "struct file" pointer
-of the file, or NULL. NULL means "let userspace handle it". 
-
-*/
-struct file *OpenFileForSecurity(char *Filename)
-{
-	struct file *filp;
-	struct DynamicString *List;
-	umode_t permission;
-	
-	
-
-	EnterFunction("OpenFileForSecurity");
-	if (Filename==NULL)
-		return NULL;
-	
-	if (strlen(Filename)>=256 ) return NULL;  /* Sanity check */
-	
-	/* Rule no. 1  -- No "?" characters */
-#ifndef BENCHMARK	
-	if (strchr(Filename,'?')!=NULL)
-		return NULL;
-
-	/* Intermediate step: decode all %hex sequences */
-	
-	DecodeHexChars(Filename);
-
-	/* Rule no. 2  -- Must start with a "/" */
-	
-	
-	if (Filename[0]!='/')
-		return NULL;
-		
-#endif
-	/* Rule no. 3 -- Does the file exist ? */
-
-	filp = filp_open(Filename, O_RDONLY, 0);
-	
-	if (IS_ERR(filp))
-		return NULL;
-
-#ifndef BENCHMARK		
-	permission = filp->f_dentry->d_inode->i_mode;
-	
-	/* Rule no. 4 : must have enough permissions */
-	
-	
-	if ((permission & sysctl_khttpd_permreq)==0)
-	{
-		if (filp!=NULL)
-			fput(filp);
-		filp=NULL;
-		return NULL;
-	}
-		
-	/* Rule no. 5 : cannot have "forbidden" permission */
-	
-	
-	if ((permission & sysctl_khttpd_permforbid)!=0)
-	{
-		if (filp!=NULL)
-			fput(filp);
-		filp=NULL;
-		return NULL;
-	}
-		
-	/* Rule no. 6 : No string in DynamicList can be a
-			substring of the filename */
-			
-	
-	List = DynamicList;
-	
-	while (List!=NULL)
-	{
-		if (strstr(Filename,List->value)!=NULL)
-		{
-			if (filp!=NULL)
-				fput(filp);
-			filp=NULL;
-			return NULL;
-		}
-		List = List->Next;
-	}
-	
-#endif	
-	LeaveFunction("OpenFileForSecurity - success");
-
-	return filp;
-}
-
-/* 
-
-DecodeHexChars does the actual %HEX decoding, in place. 
-In place is possible because strings only get shorter by this.
-
-*/
-static void DecodeHexChars(char *URL)
-{
-	char *Source,*Dest;
-	int val,val2;
-	
-	EnterFunction("DecodeHexChars");
-	
-	Source = strchr(URL,'%');
-	
-	if (Source==NULL) 
-		return;
-		
-	Dest = Source;
-	
-	while (*Source!=0)
-	{
-		if (*Source=='%')
-		{
-			Source++;
-			val = *Source;
-			
-			if (val>'Z') val-=0x20;
-			val = val - '0';
-			if (val<0) val=0; 
-			if (val>9) val-=7;
-			if (val>15) val=15;
-			
-			Source++;
-
-			val2 = *Source;
-			
-			if (val2>'Z') val2-=0x20;
-			val2 = val2 - '0';
-			if (val2<0) val2=0; 
-			if (val2>9) val2-=7;
-			if (val2>15) val2=15;
-
-			*Dest=val*16+val2;
-		} else *Dest = *Source;
-		Dest++;
-		Source++;
-	}
-	*Dest=0;	
-	
-	LeaveFunction("DecodeHexChars");
-}
-
-
-void AddDynamicString(const char *String)
-{
-	struct DynamicString *Temp;
-	
-	EnterFunction("AddDynamicString");
-	
-	Temp = (struct DynamicString*)kmalloc(sizeof(struct DynamicString),(int)GFP_KERNEL);
-	
-	if (Temp==NULL) 
-		return;
-		
-	memset(Temp->value,0,sizeof(Temp->value));
-	strncpy(Temp->value,String,sizeof(Temp->value)-1);
-	
-	Temp->Next = DynamicList;
-	DynamicList = Temp;
-	
-	LeaveFunction("AddDynamicString");
-}
-
-void GetSecureString(char *String)
-{
-	struct DynamicString *Temp;
-	int max;
-	
-	EnterFunction("GetSecureString");
-	
-	*String = 0;
-	
-	memset(String,0,255);
-	
-	strncpy(String,"Dynamic strings are : -",255);
-	Temp = DynamicList;
-	while (Temp!=NULL)
-	{
-		max=253 - strlen(String) - strlen(Temp->value);
-		strncat(String,Temp->value,max);
-		max=253 - strlen(String) - 3;
-		strncat(String,"- -",max);
-		Temp = Temp->Next;
-	}	
-	
-	LeaveFunction("GetSecureString");
-}
diff -Nru a/net/khttpd/security.h b/net/khttpd/security.h
--- a/net/khttpd/security.h	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,12 +0,0 @@
-#ifndef _INCLUDE_GUARD_SECURITY_H
-#define _INCLUDE_GUARD_SECURITY_H
-
-struct DynamicString;
-
-struct DynamicString
-{
-	struct DynamicString* Next;
-	char value[32-sizeof(void*)];  /* fill 1 cache-line */
-};
-
-#endif
diff -Nru a/net/khttpd/sockets.c b/net/khttpd/sockets.c
--- a/net/khttpd/sockets.c	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,101 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Basic socket functions
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-#include "prototypes.h"
-#include <linux/kernel.h>
-#include <linux/net.h>
-#include <linux/version.h>
-#include <linux/smp_lock.h>
-#include <net/sock.h>
-
-
-/*
-
-MainSocket is shared by all threads, therefore it has to be
-a global variable.
-
-*/
-struct socket *MainSocket=NULL;
-
-
-int StartListening(const int Port)
-{
-	struct socket *sock;
-	struct sockaddr_in sin;
-	int error;
-	
-	EnterFunction("StartListening");
-	
-	/* First create a socket */
-	
-	error = sock_create(PF_INET,SOCK_STREAM,IPPROTO_TCP,&sock);
-	if (error<0) 
-	     (void)printk(KERN_ERR "Error during creation of socket; terminating\n");
-
-
-
-	/* Now bind the socket */
-	
-	sin.sin_family	     = AF_INET;
-	sin.sin_addr.s_addr  = INADDR_ANY;
-	sin.sin_port         = htons((unsigned short)Port);
-	
-	error = sock->ops->bind(sock,(struct sockaddr*)&sin,sizeof(sin));
-	if (error<0)
-	{
-		(void)printk(KERN_ERR "kHTTPd: Error binding socket. This means that some other \n");
-		(void)printk(KERN_ERR "        daemon is (or was a short time ago) using port %i.\n",Port);
-		return 0;	
-	}
-
-	/* Grrr... setsockopt() does this. */
-	sock->sk->reuse   = 1;
-
-	/* Now, start listening on the socket */
-	
-	/* I have no idea what a sane backlog-value is. 48 works so far. */
-	
-	error=sock->ops->listen(sock,48);	
-	if (error!=0)
-		(void)printk(KERN_ERR "kHTTPd: Error listening on socket \n");
-	
-	MainSocket = sock;
-	
-	LeaveFunction("StartListening");
-	return 1; 
-}	
-
-void StopListening(void)
-{
-	struct socket *sock;
-	
-	EnterFunction("StopListening");
-	if (MainSocket==NULL) return;
-	
-	sock=MainSocket;
-	MainSocket = NULL;
-	sock_release(sock);
-
-	LeaveFunction("StopListening");
-}
diff -Nru a/net/khttpd/structure.h b/net/khttpd/structure.h
--- a/net/khttpd/structure.h	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-#ifndef _INCLUDE_GUARD_STRUCTURE_H_
-#define _INCLUDE_GUARD_STRUCTURE_H_
-
-#include <linux/time.h>
-#include <linux/wait.h>
-
-
-struct http_request;
-
-struct http_request
-{
-	/* Linked list */
-	struct http_request *Next;
-	
-	/* Network and File data */
-	struct socket	*sock;		
-	struct file	*filp;		
-
-	/* Raw data about the file */
-	
-	int		FileLength;	/* File length in bytes */
-	int		Time;		/* mtime of the file, unix format */
-	int		BytesSent;	/* The number of bytes already sent */
-	int		IsForUserspace;	/* 1 means let Userspace handle this one */
-	
-	/* Wait queue */
-	
-	wait_queue_t sleep;		/* For putting in the socket's waitqueue */
-	
-	/* HTTP request information */
-	char		FileName[256];	/* The requested filename */
-	int		FileNameLength; /* The length of the string representing the filename */
-	char		Agent[128];	/* The agent-string of the remote browser */
-	char		IMS[128];	/* If-modified-since time, rfc string format */
-	char		Host[128];	/* Value given by the Host: header */
-	int		HTTPVER;        /* HTTP-version; 9 for 0.9,   10 for 1.0 and above */
-
-
-	/* Derived date from the above fields */	
-	int		IMS_Time;	/* if-modified-since time, unix format */
-	char		TimeS[64];	/* File mtime, rfc string representation */
-	char		LengthS[14];	/* File length, string representation */
-	char		*MimeType;	/* Pointer to a string with the mime-type 
-					   based on the filename */
-	__kernel_size_t	MimeLength;	/* The length of this string */
-	
-};
-
-
-
-/*
-
-struct khttpd_threadinfo represents the four queues that 1 thread has to deal with.
-It is padded to occupy 1 (Intel) cache-line, to avoid "cacheline-pingpong".
-
-*/
-struct khttpd_threadinfo
-{
-	struct http_request* WaitForHeaderQueue;
-	struct http_request* DataSendingQueue;
-	struct http_request* LoggingQueue;
-	struct http_request* UserspaceQueue;
-	char  dummy[16];  /* Padding for cache-lines */
-};
-
-
-
-#endif
diff -Nru a/net/khttpd/sysctl.c b/net/khttpd/sysctl.c
--- a/net/khttpd/sysctl.c	Thu Aug  1 14:17:41 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,320 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Sysctl interface
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/smp_lock.h>
-#include <linux/sysctl.h>
-#include <linux/un.h>
-#include <linux/unistd.h>
-
-#include <net/ip.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-
-#include <asm/atomic.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-#include <linux/file.h>
-#include "prototypes.h"
-
-
-
-char 	sysctl_khttpd_docroot[200] = "/var/www";
-int 	sysctl_khttpd_stop 	= 0;
-int 	sysctl_khttpd_start 	= 0;
-int 	sysctl_khttpd_unload 	= 0;
-int 	sysctl_khttpd_clientport = 80;
-int 	sysctl_khttpd_permreq    = S_IROTH; /* "other" read-access is required by default*/
-int 	sysctl_khttpd_permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR;
- 				/* forbidden is execute, directory and sticky*/
-int 	sysctl_khttpd_logging 	= 0;
-int 	sysctl_khttpd_serverport= 8080;
-
-char	sysctl_khttpd_dynamicstring[200];
-int 	sysctl_khttpd_sloppymime= 0;
-int	sysctl_khttpd_threads	= 2;
-int	sysctl_khttpd_maxconnect = 1000;
-
-
-static struct ctl_table_header *khttpd_table_header;
-
-static int sysctl_SecureString(ctl_table *table, int *name, int nlen,
-		  void *oldval, size_t *oldlenp,
-		  void *newval, size_t newlen, void **context);
-static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
-		  void *buffer, size_t *lenp);
-
-
-static ctl_table khttpd_table[] = {
-	{	NET_KHTTPD_DOCROOT,
-		"documentroot",
-		&sysctl_khttpd_docroot,
-		sizeof(sysctl_khttpd_docroot),
-		0644,
-		NULL,
-		proc_dostring,
-		&sysctl_string,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_STOP,
-		"stop",
-		&sysctl_khttpd_stop,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_START,
-		"start",
-		&sysctl_khttpd_start,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_UNLOAD,
-		"unload",
-		&sysctl_khttpd_unload,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_THREADS,
-		"threads",
-		&sysctl_khttpd_threads,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_MAXCONNECT,
-		"maxconnect",
-		&sysctl_khttpd_maxconnect,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_SLOPPYMIME,
-		"sloppymime",
-		&sysctl_khttpd_sloppymime,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_CLIENTPORT,
-		"clientport",
-		&sysctl_khttpd_clientport,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_PERMREQ,
-		"perm_required",
-		&sysctl_khttpd_permreq,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_PERMFORBID,
-		"perm_forbid",
-		&sysctl_khttpd_permforbid,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_LOGGING,
-		"logging",
-		&sysctl_khttpd_logging,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_SERVERPORT,
-		"serverport",
-		&sysctl_khttpd_serverport,
-		sizeof(int),
-		0644,
-		NULL,
-		proc_dointvec,
-		&sysctl_intvec,
-		NULL,
-		NULL,
-		NULL
-	},
-	{	NET_KHTTPD_DYNAMICSTRING,
-		"dynamic",
-		&sysctl_khttpd_dynamicstring,
-		sizeof(sysctl_khttpd_dynamicstring),
-		0644,
-		NULL,
-		proc_dosecurestring,
-		&sysctl_SecureString,
-		NULL,
-		NULL,
-		NULL
-	},
-	{0,0,0,0,0,0,0,0,0,0,0}	};
-	
-	
-static ctl_table khttpd_dir_table[] = {
-	{NET_KHTTPD, "khttpd", NULL, 0, 0555, khttpd_table,0,0,0,0,0},
-	{0,0,0,0,0,0,0,0,0,0,0}
-};
-
-static ctl_table khttpd_root_table[] = {
-	{CTL_NET, "net", NULL, 0, 0555, khttpd_dir_table,0,0,0,0,0},
-	{0,0,0,0,0,0,0,0,0,0,0}
-};
-	
-
-void StartSysctl(void)
-{
-	khttpd_table_header = register_sysctl_table(khttpd_root_table,1);
-}
-
-
-void EndSysctl(void)
-{
-	unregister_sysctl_table(khttpd_table_header);
-}
-
-static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
-		  void *buffer, size_t *lenp)
-{
-	size_t len;
-	char *p, c=0;
-	char String[256];
-	
-	if ((table->data==0) || (table->maxlen==0) || (*lenp==0) ||
-	    ((filp->f_pos!=0) && (write==0))) {
-		*lenp = 0;
-		return 0;
-	}
-	
-	if (write!=0) {
-		len = 0;
-		p = buffer;
-		while (len < *lenp) {
-			if(get_user(c, p++))
-				return -EFAULT;
-			if (c == 0 || c == '\n')
-				break;
-			len++;
-		}
-		if (len >= table->maxlen)
-			len = table->maxlen-1;
-		if(copy_from_user(String, buffer,(unsigned long)len))
-			return -EFAULT;
-		((char *) String)[len] = 0;
-		filp->f_pos += *lenp;
-		AddDynamicString(String);
-	} else {
-		GetSecureString(String);
-		len = strlen(String);
-		if (len > table->maxlen)
-			len = table->maxlen;
-		if (len > *lenp)
-			len = *lenp;
-		if (len!=0)
-			if(copy_to_user(buffer, String,(unsigned long)len))
-				return -EFAULT;
-		if (len < *lenp) {
-			if(put_user('\n', ((char *) buffer) + len))
-				return -EFAULT;
-			len++;
-		}
-		*lenp = len;
-		filp->f_pos += len;
-	}
-	return 0;
-}
-
-static int sysctl_SecureString (/*@unused@*/ctl_table *table, 
-				/*@unused@*/int *name, 
-				/*@unused@*/int nlen,
-		  		/*@unused@*/void *oldval, 
-		  		/*@unused@*/size_t *oldlenp,
-		  		/*@unused@*/void *newval, 
-		  		/*@unused@*/size_t newlen, 
-		  		/*@unused@*/void **context)
-{
-	return -ENOSYS;
-}
diff -Nru a/net/khttpd/sysctl.h b/net/khttpd/sysctl.h
--- a/net/khttpd/sysctl.h	Thu Aug  1 14:17:39 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,17 +0,0 @@
-#ifndef _KHTTPD_INCLUDE_GUARD_SYSCTL_H
-#define _KHTTPD_INCLUDE_GUARD_SYSCTL_H
-
-extern char 	sysctl_khttpd_docroot[200];
-extern int 	sysctl_khttpd_stop;
-extern int 	sysctl_khttpd_start;
-extern int 	sysctl_khttpd_unload;
-extern int 	sysctl_khttpd_clientport;
-extern int 	sysctl_khttpd_permreq;
-extern int 	sysctl_khttpd_permforbid;
-extern int 	sysctl_khttpd_logging;
-extern int 	sysctl_khttpd_serverport;
-extern int 	sysctl_khttpd_sloppymime;
-extern int 	sysctl_khttpd_threads;
-extern int	sysctl_khttpd_maxconnect;
-
-#endif
diff -Nru a/net/khttpd/userspace.c b/net/khttpd/userspace.c
--- a/net/khttpd/userspace.c	Thu Aug  1 14:17:36 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,243 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Pass connections to userspace-daemons
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-/*
-
-Purpose:
-
-Userspace() hands all requests in the queue to the userspace-daemon, if
-such beast exists.
-
-Return value:
-	The number of requests that changed status
-*/
-#include <linux/kernel.h>
-
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/net.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/smp_lock.h>
-#include <linux/un.h>
-#include <linux/unistd.h>
-#include <linux/wait.h>
-
-#include <net/ip.h>
-#include <net/sock.h>
-#include <net/tcp.h>
-
-#include <asm/atomic.h>
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/uaccess.h>
-
-#include <linux/file.h>
-
-
-#include "structure.h"
-#include "prototypes.h"
-#include "sysctl.h"
-
-/* prototypes of local, static functions */
-static int AddSocketToAcceptQueue(struct socket *sock,const int Port);
-
-
-int Userspace(const int CPUNR)
-{
-	struct http_request *CurrentRequest,**Prev,*Next;
-	
-	EnterFunction("Userspace");
-
-	
-
-	
-	CurrentRequest = threadinfo[CPUNR].UserspaceQueue;
-	Prev = &(threadinfo[CPUNR].UserspaceQueue);
-	
-	while (CurrentRequest!=NULL)
-	{
-
-		/* Clean-up the waitqueue of the socket.. Bad things happen if
-		   this is forgotten. */
-		if (CurrentRequest->sock!=NULL)
-		{
-			if ((CurrentRequest->sock!=NULL)&&(CurrentRequest->sock->sk!=NULL))
-			{
-				remove_wait_queue(CurrentRequest->sock->sk->sleep,&(CurrentRequest->sleep));
-			}
-		} 
-		
-
-		if  (AddSocketToAcceptQueue(CurrentRequest->sock,sysctl_khttpd_clientport)>=0)
-		{
-			
-			(*Prev) = CurrentRequest->Next;
-			Next = CurrentRequest->Next;
-			
-			
-			sock_release(CurrentRequest->sock);
-			CurrentRequest->sock = NULL;	 /* We no longer own it */
-			
-			CleanUpRequest(CurrentRequest); 
-				
-			CurrentRequest = Next;
-			continue;
-		
-		}
-		else /* No userspace-daemon present, or other problems with it */
-		{
-			(*Prev) = CurrentRequest->Next;
-			Next = CurrentRequest->Next;
-			
-			Send403(CurrentRequest->sock); /* Sorry, no go... */
-			
-			CleanUpRequest(CurrentRequest); 
-				
-			CurrentRequest = Next;
-			continue;
-		
-		}
-
-		
-		Prev = &(CurrentRequest->Next);	
-		CurrentRequest = CurrentRequest->Next;
-	}
-	
-	LeaveFunction("Userspace");
-	return 0;
-}
-
-void StopUserspace(const int CPUNR)
-{
-	struct http_request *CurrentRequest,*Next;
-	
-	EnterFunction("StopUserspace");
-	CurrentRequest = threadinfo[CPUNR].UserspaceQueue;
-
-	while (CurrentRequest!=NULL)
-	{
-		Next= CurrentRequest->Next;
-		CleanUpRequest(CurrentRequest);
-		CurrentRequest=Next;		
-	}
-	threadinfo[CPUNR].UserspaceQueue = NULL;
-	
-	LeaveFunction("StopUserspace");
-}
-
-
-/* 
-   "FindUserspace" returns the struct sock of the userspace-daemon, so that we can
-   "drop" our request in the accept-queue 
-*/
-
-static struct sock *FindUserspace(const unsigned short Port)
-{
-	struct sock *sk;
-
-	EnterFunction("FindUserspace");
-
-	local_bh_disable();
-	sk = tcp_v4_lookup_listener(INADDR_ANY,Port,0);
-	local_bh_enable();
-	return sk;
-}
-
-static void dummy_destructor(struct open_request *req)
-{
-}
-
-static struct or_calltable Dummy = 
-{
-	0,
- 	NULL,
- 	NULL,
- 	&dummy_destructor,
- 	NULL
-};
-
-static int AddSocketToAcceptQueue(struct socket *sock,const int Port)
-{
-	struct open_request *req;
-	struct sock *sk, *nsk;
-	
-	EnterFunction("AddSocketToAcceptQueue");
-
-	
-	sk = FindUserspace((unsigned short)Port);	
-	
-	if (sk==NULL)   /* No userspace-daemon found */
-	{
-		return -1;
-	}
-	
-	lock_sock(sk);
-
-	if (sk->state != TCP_LISTEN || tcp_acceptq_is_full(sk))
-	{
-		release_sock(sk);
-		sock_put(sk);
-		return -1;
-	}
-
-	req = tcp_openreq_alloc();
-	
-	if (req==NULL)
-	{	
-		release_sock(sk);
-		sock_put(sk);
-		return -1;
-	}
-	
-	nsk = sock->sk;
-	sock->sk = NULL;
-	sock->state = SS_UNCONNECTED;
-
-	req->class	= &Dummy;
-	write_lock_bh(&nsk->callback_lock);
-	nsk->socket = NULL;
-        nsk->sleep  = NULL;
-	write_unlock_bh(&nsk->callback_lock);
-
-	tcp_acceptq_queue(sk, req, nsk);	
-
-	sk->data_ready(sk, 0);
-
-	release_sock(sk);
-	sock_put(sk);
-
-	LeaveFunction("AddSocketToAcceptQueue");
-		
-	return +1;	
-	
-	
-	
-}
-
-void InitUserspace(const int CPUNR)
-{
-}
-
-
diff -Nru a/net/khttpd/waitheaders.c b/net/khttpd/waitheaders.c
--- a/net/khttpd/waitheaders.c	Thu Aug  1 14:17:39 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,298 +0,0 @@
-/*
-
-kHTTPd -- the next generation
-
-Wait for headers on the accepted connections
-
-*/
-/****************************************************************
- *	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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ****************************************************************/
-
-/*
-
-Purpose:
-
-WaitForHeaders polls all connections in "WaitForHeaderQueue" to see if
-headers have arived. If so, the headers are decoded and the request is
-moved to either the "SendingDataQueue" or the "UserspaceQueue".
-
-Return value:
-	The number of requests that changed status
-*/
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/smp_lock.h>
-#include <linux/file.h>
-
-#include <asm/uaccess.h>
-
-#include "structure.h"
-#include "prototypes.h"
-
-static	char			*Buffer[CONFIG_KHTTPD_NUMCPU];
-
-
-static int DecodeHeader(const int CPUNR, struct http_request *Request);
-
-
-int WaitForHeaders(const int CPUNR)
-{
-	struct http_request *CurrentRequest,**Prev;
-	struct sock *sk;
-	int count = 0;
-	
-	EnterFunction("WaitForHeaders");
-	
-	CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
-	
-	Prev = &(threadinfo[CPUNR].WaitForHeaderQueue);
-	
-	while (CurrentRequest!=NULL)
-	{
-		
-		/* If the connection is lost, remove from queue */
-		
-		if (CurrentRequest->sock->sk->state != TCP_ESTABLISHED
-		    && CurrentRequest->sock->sk->state != TCP_CLOSE_WAIT)
-		{
-			struct http_request *Next;
-			
-			Next = CurrentRequest->Next;
-			
-			*Prev = CurrentRequest->Next;
-			CurrentRequest->Next = NULL;
-			
-		
-			CleanUpRequest(CurrentRequest);
-			CurrentRequest = Next;
-			continue;
-		}
-		
-		
-		
-		/* If data pending, take action */	
-		
-		sk = CurrentRequest->sock->sk;
-		
-		if (!skb_queue_empty(&(sk->receive_queue))) /* Do we have data ? */
-		{
-			struct http_request *Next;
-			
-			
-			
-			/* Decode header */
-			
-			if (DecodeHeader(CPUNR,CurrentRequest)<0)
-			{
-				CurrentRequest = CurrentRequest->Next;
-				continue;
-			} 
-			
-			
-			/* Remove from WaitForHeaderQueue */		
-			
-			Next= CurrentRequest->Next;
-		
-			*Prev = Next;
-			count++;
-			
-			/* Add to either the UserspaceQueue or the DataSendingQueue */
-			
-			if (CurrentRequest->IsForUserspace!=0)
-			{
-				CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue;
-				threadinfo[CPUNR].UserspaceQueue = CurrentRequest;	
-			} else
-			{
-				CurrentRequest->Next = threadinfo[CPUNR].DataSendingQueue;
-				threadinfo[CPUNR].DataSendingQueue = CurrentRequest;	
-			} 	
-			
-			CurrentRequest = Next;
-			continue;
-		
-		}	
-
-		
-		Prev = &(CurrentRequest->Next);
-		CurrentRequest = CurrentRequest->Next;
-	}
-
-	LeaveFunction("WaitHeaders");
-	return count;
-}
-
-void StopWaitingForHeaders(const int CPUNR)
-{
-	struct http_request *CurrentRequest,*Next;
-	
-	EnterFunction("StopWaitingForHeaders");
-	CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
-
-	while (CurrentRequest!=NULL)
-	{
-		Next = CurrentRequest->Next;
-		CleanUpRequest(CurrentRequest);
-		CurrentRequest=Next;		
-	}
-	
-	threadinfo[CPUNR].WaitForHeaderQueue = NULL; /* The queue is empty now */
-	
-	free_page((unsigned long)Buffer[CPUNR]);
-	Buffer[CPUNR]=NULL;
-	
-	EnterFunction("StopWaitingForHeaders");
-}
-
-
-/* 
-
-DecodeHeader peeks at the TCP/IP data, determines what the request is, 
-fills the request-structure and sends the HTTP-header when apropriate.
-
-*/
-
-static int DecodeHeader(const int CPUNR, struct http_request *Request)
-{
-	struct msghdr		msg;
-	struct iovec		iov;
-	int			len;
-
-	mm_segment_t		oldfs;
-	
-	EnterFunction("DecodeHeader");
-	
-	/* First, read the data */
-
-	msg.msg_name     = 0;
-	msg.msg_namelen  = 0;
-	msg.msg_iov	 = &iov;
-	msg.msg_iovlen   = 1;
-	msg.msg_control  = NULL;
-	msg.msg_controllen = 0;
-	msg.msg_flags    = 0;
-	
-	msg.msg_iov->iov_base = &Buffer[CPUNR][0];
-	msg.msg_iov->iov_len  = (size_t)4095;
-	
-	len = 0;
-	oldfs = get_fs(); set_fs(KERNEL_DS);
-	/* 4095 leaves a "0" to terminate the string */
-	
-	len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK);
-	set_fs(oldfs);
-
-	if (len<0) {
-		/* WONDERFUL. NO COMMENTS. --ANK */
-		Request->IsForUserspace = 1;
-		return 0;
-	}
-
-	if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */	
-	{
-		Request->IsForUserspace = 1;
-		return 0;
-	}
-	
-	/* Then, decode the header */
-	
-	
-	ParseHeader(Buffer[CPUNR],len,Request);
-	
-	Request->filp = OpenFileForSecurity(Request->FileName);
-	
-	
-	Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength);
-	
-	
-	if (Request->MimeType==NULL) /* Unknown mime-type */
-	{
-		if (Request->filp!=NULL)
-		{
-			fput(Request->filp);
-			Request->filp = NULL;
-		}
-		Request->IsForUserspace = 1;
-		
-		return 0;
-	}
-
-	if (Request->filp==NULL)
-	{
-		Request->IsForUserspace = 1;
-		return 0;
-	}
-	else
-	{
-		Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
-		Request->Time       = Request->filp->f_dentry->d_inode->i_mtime;
-		Request->IMS_Time   = mimeTime_to_UnixTime(Request->IMS);
-		sprintf(Request->LengthS,"%i",Request->FileLength);
-		time_Unix2RFC(min_t(unsigned int, Request->Time,CurrentTime_i),Request->TimeS);
-   	        /* The min() is required by rfc1945, section 10.10:
-   	           It is not allowed to send a filetime in the future */
-
-		if (Request->IMS_Time>Request->Time)
-		{	/* Not modified since last time */
-			Send304(Request->sock);
-			Request->FileLength=0;
-		}
-		else   /* Normal Case */
-		{
-			struct tcp_opt *tp = tcp_sk(Request->sock->sk);
-
-			tp->nonagle = 2; /* this is TCP_CORK */
-			if (Request->HTTPVER!=9)  /* HTTP/0.9 doesn't allow a header */
-				SendHTTPHeader(Request);
-		}
-		
-	
-	}
-	
-	LeaveFunction("DecodeHeader");
-	return 0;
-}
-
-
-int InitWaitHeaders(int ThreadCount)
-{
-	int I,I2;
-
-	EnterFunction("InitWaitHeaders");
-	I=0;	
-	while (I<ThreadCount)
-	{
-		Buffer[I] = (char*)get_free_page((int)GFP_KERNEL);
-		if (Buffer[I] == NULL) 
-		{
-			printk(KERN_CRIT "kHTTPd: Not enough memory for basic needs\n");
-			I2=0;
-			while (I2<I-1)
-			{
-				free_page( (unsigned long)Buffer[I2++]);
-			}
-			return -1;
-		}
-		I++;
-	}
-	
-	LeaveFunction("InitWaitHeaders");	
-	return 0;
-
-}
diff -Nru a/net/netlink/Makefile b/net/netlink/Makefile
--- a/net/netlink/Makefile	Thu Aug  1 14:17:40 2002
+++ b/net/netlink/Makefile	Thu Aug  1 14:17:40 2002
@@ -2,8 +2,6 @@
 # Makefile for the netlink driver.
 #
 
-export-objs := af_netlink.o
-
 obj-y  				:= af_netlink.o
 obj-$(CONFIG_NETLINK_DEV)	+= netlink_dev.o
 
diff -Nru a/net/netlink/netlink_dev.c b/net/netlink/netlink_dev.c
--- a/net/netlink/netlink_dev.c	Thu Aug  1 14:17:40 2002
+++ b/net/netlink/netlink_dev.c	Thu Aug  1 14:17:40 2002
@@ -182,7 +182,7 @@
 
 int __init init_netlink(void)
 {
-	if (devfs_register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) {
+	if (register_chrdev(NETLINK_MAJOR,"netlink", &netlink_fops)) {
 		printk(KERN_ERR "netlink: unable to get major %d\n", NETLINK_MAJOR);
 		return -EIO;
 	}
@@ -217,7 +217,7 @@
 void cleanup_module(void)
 {
 	devfs_unregister (devfs_handle);
-	devfs_unregister_chrdev(NETLINK_MAJOR, "netlink");
+	unregister_chrdev(NETLINK_MAJOR, "netlink");
 }
 
 #endif
diff -Nru a/net/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Thu Aug  1 14:17:40 2002
+++ b/net/netsyms.c	Thu Aug  1 14:17:40 2002
@@ -56,7 +56,7 @@
 
 extern struct net_proto_family inet_family_ops;
 
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
 #include <linux/icmpv6.h>
 #include <net/ipv6.h>
@@ -286,7 +286,7 @@
 #endif
 
 
-#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
+#if defined (CONFIG_IPV6_MODULE)
 /* inet functions common to v4 and v6 */
 EXPORT_SYMBOL(inet_release);
 EXPORT_SYMBOL(inet_stream_connect);
diff -Nru a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
--- a/net/sched/sch_ingress.c	Thu Aug  1 14:17:41 2002
+++ b/net/sched/sch_ingress.c	Thu Aug  1 14:17:41 2002
@@ -106,7 +106,7 @@
 #endif
 	DPRINTK("ingress_change(sch %p,[qdisc %p],classid %x,parent %x),"
 		"arg 0x%lx\n", sch, p, classid, parent, *arg);
-	DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
+	DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment");
 	return 0;
 }
 
@@ -118,7 +118,7 @@
 	struct ingress_qdisc_data *p = PRIV(sch);
 #endif
 	DPRINTK("ingress_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
-	DPRINTK("No effect. sch_ingress doesnt maintain classes at the moment");
+	DPRINTK("No effect. sch_ingress doesn't maintain classes at the moment");
 }
 
 
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	Thu Aug  1 14:17:40 2002
+++ b/net/sunrpc/clnt.c	Thu Aug  1 14:17:40 2002
@@ -605,17 +605,17 @@
 {
 	struct rpc_clnt	*clnt = task->tk_client;
 	struct rpc_xprt *xprt = clnt->cl_xprt;
-	struct rpc_rqst	*req;
-	int		status = task->tk_status;
+	struct rpc_rqst	*req = task->tk_rqstp;
+	int		status;
+
+	if (req->rq_received != 0)
+		task->tk_status = req->rq_received;
 
 	dprintk("RPC: %4d call_status (status %d)\n", 
 				task->tk_pid, task->tk_status);
 
-	req = task->tk_rqstp;
-	if (req->rq_received != 0)
-		status = req->rq_received;
+	status = task->tk_status;
 	if (status >= 0) {
-		req->rq_received = 0;
 		task->tk_action = call_decode;
 		return;
 	}
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	Thu Aug  1 14:17:36 2002
+++ b/net/sunrpc/xprt.c	Thu Aug  1 14:17:36 2002
@@ -137,17 +137,14 @@
  * Also prevents TCP socket reconnections from colliding with writes.
  */
 static int
-xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+__xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-	int retval;
-	spin_lock_bh(&xprt->sock_lock);
 	if (!xprt->snd_task) {
 		if (xprt->nocong || __xprt_get_cong(xprt, task))
 			xprt->snd_task = task;
 	}
 	if (xprt->snd_task != task) {
-		dprintk("RPC: %4d TCP write queue full (task %d)\n",
-			task->tk_pid, xprt->snd_task->tk_pid);
+		dprintk("RPC: %4d TCP write queue full\n", task->tk_pid);
 		task->tk_timeout = 0;
 		task->tk_status = -EAGAIN;
 		if (task->tk_rqstp->rq_nresend)
@@ -155,11 +152,21 @@
 		else
 			rpc_sleep_on(&xprt->sending, task, NULL, NULL);
 	}
-	retval = xprt->snd_task == task;
+	return xprt->snd_task == task;
+}
+
+static inline int
+xprt_lock_write(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+	int retval;
+
+	spin_lock_bh(&xprt->sock_lock);
+	retval = __xprt_lock_write(xprt, task);
 	spin_unlock_bh(&xprt->sock_lock);
 	return retval;
 }
 
+
 static void
 __xprt_lock_write_next(struct rpc_xprt *xprt)
 {
@@ -564,8 +571,8 @@
 #endif
 
 	dprintk("RPC: %4d has input (%d bytes)\n", task->tk_pid, copied);
-	task->tk_status = copied;
 	req->rq_received = copied;
+	list_del_init(&req->rq_list);
 
 	/* ... and wake up the process. */
 	rpc_wake_up_task(task);
@@ -1057,8 +1064,16 @@
 		*marker = htonl(0x80000000|(req->rq_slen-sizeof(*marker)));
 	}
 
-	if (!xprt_lock_write(xprt, task))
+	spin_lock_bh(&xprt->sock_lock);
+	if (!__xprt_lock_write(xprt, task)) {
+		spin_unlock_bh(&xprt->sock_lock);
 		return;
+	}
+	if (list_empty(&req->rq_list)) {
+		list_add_tail(&req->rq_list, &xprt->recv);
+		req->rq_received = 0;
+	}
+	spin_unlock_bh(&xprt->sock_lock);
 
 	do_xprt_transmit(task);
 }
@@ -1242,9 +1257,6 @@
 	if (!xid)
 		xid++;
 	INIT_LIST_HEAD(&req->rq_list);
-	spin_lock_bh(&xprt->sock_lock);
-	list_add_tail(&req->rq_list, &xprt->recv);
-	spin_unlock_bh(&xprt->sock_lock);
 }
 
 /*
diff -Nru a/scripts/fixdep.c b/scripts/fixdep.c
--- a/scripts/fixdep.c	Thu Aug  1 14:17:40 2002
+++ b/scripts/fixdep.c	Thu Aug  1 14:17:40 2002
@@ -213,7 +213,7 @@
 void parse_config_file(char *map, size_t len)
 {
 	int *end = (int *) (map + len);
-	// start at +1, so that p can never be < map
+	/* start at +1, so that p can never be < map */
 	int *m   = (int *) map + 1;
 	char *p, *q;
 
@@ -283,7 +283,7 @@
 void parse_dep_file(void *map, size_t len)
 {
 	char *m = map;
-	char *end = map + len;
+	char *end = m + len;
 	char *p;
 	char s[PATH_MAX];
 
diff -Nru a/scripts/mkcompile_h b/scripts/mkcompile_h
--- a/scripts/mkcompile_h	Thu Aug  1 14:17:41 2002
+++ b/scripts/mkcompile_h	Thu Aug  1 14:17:41 2002
@@ -3,6 +3,20 @@
 SMP=$3
 CC=$4
 
+# If compile.h exists already and we don't own autoconf.h
+# (i.e. we're not the same user who did make *config), don't
+# modify compile.h
+# So "sudo make install" won't change the "compiled by <user>"
+# do "compiled by root"
+
+if [ -r $TARGET -a ! -O ../include/linux/autoconf.h ]; then
+  echo ' (not modified)'
+  exit 0
+fi
+
+# Do not expand names
+set -f
+
 if [ -r ../.version ]; then
   VERSION=`cat ../.version`
 else
diff -Nru a/security/capability.c b/security/capability.c
--- a/security/capability.c	Thu Aug  1 14:17:40 2002
+++ b/security/capability.c	Thu Aug  1 14:17:40 2002
@@ -464,7 +464,7 @@
 	return 0;
 }
 
-static int cap_file_lock (struct file *file, unsigned int cmd, int blocking)
+static int cap_file_lock (struct file *file, unsigned int cmd)
 {
 	return 0;
 }
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	Thu Aug  1 14:17:37 2002
+++ b/security/dummy.c	Thu Aug  1 14:17:37 2002
@@ -366,7 +366,7 @@
 	return 0;
 }
 
-static int dummy_file_lock (struct file *file, unsigned int cmd, int blocking)
+static int dummy_file_lock (struct file *file, unsigned int cmd)
 {
 	return 0;
 }
diff -Nru a/sound/core/Makefile b/sound/core/Makefile
--- a/sound/core/Makefile	Thu Aug  1 14:17:36 2002
+++ b/sound/core/Makefile	Thu Aug  1 14:17:36 2002
@@ -3,7 +3,7 @@
 # Copyright (c) 1999,2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-export-objs  := sound.o pcm.o pcm_lib.o rawmidi.o timer.o rtctimer.o hwdep.o
+export-objs  := sound.o pcm.o pcm_lib.o rawmidi.o timer.o hwdep.o
 
 snd-objs     := sound.o init.o isadma.o memory.o info.o control.o misc.o \
                 device.o wrappers.o
diff -Nru a/sound/core/info.c b/sound/core/info.c
--- a/sound/core/info.c	Thu Aug  1 14:17:40 2002
+++ b/sound/core/info.c	Thu Aug  1 14:17:40 2002
@@ -973,10 +973,10 @@
 		sprintf(dname, "snd/%s", entry->name);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
 		master = devfs_find_handle(NULL, dname, strlen(dname), 0, 0, DEVFS_SPECIAL_CHR, 0);
+		devfs_unregister(master);
 #else
-		master = devfs_find_handle(NULL, dname, 0, 0, DEVFS_SPECIAL_CHR, 0);
+		devfs_find_and_unregister(NULL, dname, 0, 0, DEVFS_SPECIAL_CHR, 0);
 #endif
-		devfs_unregister(master);
 	}
 #endif
 	snd_info_free_entry(entry);
diff -Nru a/sound/core/seq/Makefile b/sound/core/seq/Makefile
--- a/sound/core/seq/Makefile	Thu Aug  1 14:17:41 2002
+++ b/sound/core/seq/Makefile	Thu Aug  1 14:17:41 2002
@@ -8,7 +8,7 @@
   obj-$(CONFIG_SND_SEQUENCER) += oss/
 endif
 
-export-objs  := seq_device.o seq.o seq_ports.o seq_instr.o seq_midi_emul.o \
+export-objs  := seq_device.o seq.o seq_instr.o seq_midi_emul.o \
 		seq_midi_event.o seq_virmidi.o
 
 snd-seq-device-objs := seq_device.o
diff -Nru a/sound/core/sound.c b/sound/core/sound.c
--- a/sound/core/sound.c	Thu Aug  1 14:17:36 2002
+++ b/sound/core/sound.c	Thu Aug  1 14:17:36 2002
@@ -315,10 +315,8 @@
 #else
 	devfs_handle = devfs_mk_dir(NULL, "snd", NULL);
 #endif
-	if (devfs_register_chrdev(snd_major, "alsa", &snd_fops)) {
-#else
-	if (register_chrdev(snd_major, "alsa", &snd_fops)) {
 #endif
+	if (register_chrdev(snd_major, "alsa", &snd_fops)) {
 		snd_printk(KERN_ERR "unable to register native major device number %d\n", snd_major);
 #ifdef CONFIG_SND_OSSEMUL
 		snd_oss_cleanup_module();
@@ -368,10 +366,10 @@
 		sprintf(controlname, "snd/controlC%d", controlnum);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
 		master = devfs_find_handle(NULL, controlname, strlen(controlname), 0, 0, DEVFS_SPECIAL_CHR, 0);
+		devfs_unregister(master);
 #else
-		master = devfs_find_handle(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0);
+		devfs_find_and_unregister(NULL, controlname, 0, 0, DEVFS_SPECIAL_CHR, 0);
 #endif
-		devfs_unregister(master);
 	}
 #endif
 	
@@ -386,11 +384,7 @@
 #ifdef CONFIG_SND_DEBUG_MEMORY
 	snd_memory_done();
 #endif
-#ifdef CONFIG_DEVFS_FS
-	if (devfs_unregister_chrdev(snd_major, "alsa") != 0)
-#else
 	if (unregister_chrdev(snd_major, "alsa") != 0)
-#endif
 		snd_printk(KERN_ERR "unable to unregister major device number %d\n", snd_major);
 #ifdef CONFIG_DEVFS_FS
 	devfs_unregister(devfs_handle);
diff -Nru a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile
--- a/sound/isa/sb/Makefile	Thu Aug  1 14:17:40 2002
+++ b/sound/isa/sb/Makefile	Thu Aug  1 14:17:40 2002
@@ -3,7 +3,7 @@
 # Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
 #
 
-export-objs  := emu8000.o emu8000_synth.o sb_common.o sb8_main.o sb16_main.o sb16_csp.o
+export-objs  := emu8000.o sb_common.o sb8_main.o sb16_main.o sb16_csp.o
 
 snd-sb-common-objs := sb_common.o sb_mixer.o
 snd-sb8-dsp-objs := sb8_main.o sb8_midi.o
diff -Nru a/sound/oss/Makefile b/sound/oss/Makefile
--- a/sound/oss/Makefile	Thu Aug  1 14:17:39 2002
+++ b/sound/oss/Makefile	Thu Aug  1 14:17:39 2002
@@ -6,10 +6,9 @@
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs	:=  ad1848.o audio_syms.o midi_syms.o mpu401.o \
-		    msnd.o opl3.o sb_common.o sequencer_syms.o \
-		    sound_syms.o uart401.o	\
-		    nm256_audio.o ac97.o ac97_codec.o aci.o
+export-objs	:=  ad1848.o audio_syms.o midi_syms.o mpu401.o ac97_codec.o \
+		    msnd.o opl3.o sb_common.o sequencer_syms.o ac97.o aci.o \
+		    sound_syms.o uart401.o
 
 # Each configuration option enables a list of files.
 
diff -Nru a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
--- a/sound/oss/cs46xx.c	Thu Aug  1 14:17:36 2002
+++ b/sound/oss/cs46xx.c	Thu Aug  1 14:17:36 2002
@@ -2521,7 +2521,7 @@
 			{
 				dmabuf = &state->dmabuf;
 				stop_dac(state);
-				synchronize_irq();
+				synchronize_irq(card->irq);
 				dmabuf->ready = 0;
 				resync_dma_ptrs(state);
 				dmabuf->swptr = dmabuf->hwptr = 0;
@@ -2536,7 +2536,7 @@
 			{
 				dmabuf = &state->dmabuf;
 				stop_adc(state);
-				synchronize_irq();
+				synchronize_irq(card->irq);
 				resync_dma_ptrs(state);
 				dmabuf->ready = 0;
 				dmabuf->swptr = dmabuf->hwptr = 0;
diff -Nru a/sound/oss/i810_audio.c b/sound/oss/i810_audio.c
--- a/sound/oss/i810_audio.c	Thu Aug  1 14:17:41 2002
+++ b/sound/oss/i810_audio.c	Thu Aug  1 14:17:41 2002
@@ -1733,7 +1733,6 @@
 		}
 
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		synchronize_irq(state->card->irq);
 		dmabuf->ready = 0;
 		dmabuf->swptr = dmabuf->hwptr = 0;
 		dmabuf->count = dmabuf->total_bytes = 0;
diff -Nru a/sound/oss/soundcard.c b/sound/oss/soundcard.c
--- a/sound/oss/soundcard.c	Thu Aug  1 14:17:40 2002
+++ b/sound/oss/soundcard.c	Thu Aug  1 14:17:40 2002
@@ -566,13 +566,9 @@
 					SOUND_MAJOR, dev_list[i].minor+ (j* 0x10),
 					S_IFCHR | dev_list[i].mode,
 					&oss_sound_fops, NULL);
-			else {
-				devfs_handle_t de;
-				
-				de = devfs_find_handle (NULL, name_buf, 0, 0,
-					DEVFS_SPECIAL_CHR, 0);
-				devfs_unregister (de);
-			}
+			else
+				devfs_find_and_unregister(NULL, name_buf, 0, 0,
+							  DEVFS_SPECIAL_CHR,0);
 		}
 	}
 }
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	Thu Aug  1 14:17:41 2002
+++ b/sound/oss/trident.c	Thu Aug  1 14:17:41 2002
@@ -36,6 +36,35 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.14.10f
+ *      July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      patch from Eric Lemar (via Ian Soboroff): in suspend and resume, 
+ *      fix wrong cast from pci_dev* to struct trident_card*. 
+ *  v0.14.10e
+ *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      rewrite the DMA buffer allocation/deallcoation functions, to make it 
+ *      modular and fix a bug where we would call free_pages on memory 
+ *      obtained with pci_alloc_consistent. Also remove unnecessary #ifdef 
+ *      CONFIG_PROC_FS and various other cleanups.
+ *  v0.14.10d
+ *      July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming
+ *      my syslog with hundreds of messages. 
+ *  v0.14.10c
+ *      July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle
+ *      and the coding style used in the rest of the file. 
+ *  v0.14.10b
+ *      June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il>
+ *      add a missing unlock_set_fmt, remove a superflous lock/unlock pair 
+ *      with nothing in between. 
+ *  v0.14.10a
+ *      June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> 
+ *      use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns 
+ *      per line, use 'do {} while (0)' in statement macros. 
+ *  v0.14.10
+ *      June 6 2002 Lei Hu <Lei_hu@ali.com.tw>
+ *      rewrite the part to read/write registers of audio codec for Ali5451 
  *  v0.14.9e
  *      January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport
  *      support to avoid resource conflict with pcigame.c
@@ -161,20 +190,21 @@
 #include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
-#include <asm/io.h>
-#include <asm/dma.h>
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/ac97_codec.h>
 #include <linux/wrapper.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
 #include <linux/bitops.h>
 #include <linux/proc_fs.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/gameport.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <asm/io.h>
+#include <asm/dma.h>
 
 #if defined CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC
 #include <asm/hwrpb.h>
@@ -182,9 +212,7 @@
 
 #include "trident.h"
 
-#include <linux/pm.h>
-
-#define DRIVER_VERSION "0.14.9e"
+#define DRIVER_VERSION "0.14.10f"
 
 /* magic numbers to protect our data structures */
 #define TRIDENT_CARD_MAGIC	0x5072696E /* "Prin" */
@@ -202,7 +230,13 @@
 /* minor number of /dev/swmodem (temporary, experimental) */
 #define SND_DEV_SWMODEM	7
 
-static const unsigned ali_multi_channels_5_1[] = { /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/ ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL};
+static const unsigned ali_multi_channels_5_1[] = { 
+	/*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,*/
+	ALI_CENTER_CHANNEL, 
+	ALI_LEF_CHANNEL, 
+	ALI_SURR_LEFT_CHANNEL, 
+	ALI_SURR_RIGHT_CHANNEL
+};
 
 static const unsigned sample_size[] = { 1, 2, 2, 4 };
 static const unsigned sample_shift[] = { 0, 1, 1, 2 };
@@ -292,7 +326,7 @@
 		
 	} dmabuf;
 
-	/* 5.1channels */	
+	/* 5.1 channels */	
 	struct trident_state *other_states[4];
 	int multi_channels_adjust_count;
 	unsigned chans_num;
@@ -319,6 +353,7 @@
 	u32 aint;
 	u32 aint_en;
 };
+
 static struct trident_pcm_bank_address bank_a_addrs =
 {
 	T4D_START_A,
@@ -326,6 +361,7 @@
 	T4D_AINT_A,
 	T4D_AINTEN_A
 };
+
 static struct trident_pcm_bank_address bank_b_addrs =
 {
 	T4D_START_B,
@@ -333,6 +369,7 @@
 	T4D_AINT_B,
 	T4D_AINTEN_B
 };
+
 struct trident_pcm_bank {
 	/* register addresses to control bank operations */
 	struct trident_pcm_bank_address *addresses;
@@ -398,6 +435,7 @@
 	HSET, MIC, MODEM_LINE1, MODEM_LINE2,
 	I2S_LR, SPDIF_LR
 };
+
 /* table to map from channel attribute to CHANNELMASK for SiS 7018 */
 static int attr2mask [] = {
 	DSP_BIND_MODEM1, DSP_BIND_MODEM2, DSP_BIND_FRONT, DSP_BIND_HANDSET,
@@ -406,7 +444,7 @@
 
 /* Added by Matt Wu 01-05-2001 for spdif in */
 static int ali_close_multi_channels(void);
-static void ali_delay(struct trident_card *card,int interval);
+static void ali_delay(struct trident_card *card, int interval);
 static void ali_detect_spdif_rate(struct trident_card *card);
 
 static void ali_ac97_write(struct ac97_codec *codec, u8 reg, u16 val);
@@ -438,8 +476,11 @@
 static void ali_disable_spdif_in(struct trident_card *card);
 static void ali_disable_special_channel(struct trident_card *card, int ch);
 static void ali_setup_spdif_out(struct trident_card *card, int flag);
-static int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt);
-static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums);
+static int ali_write_5_1(struct trident_state *state, const char *buffer,
+			 int cnt_for_multi_channel, unsigned int *copy_count, 
+			 unsigned int *state_cnt);
+static int ali_allocate_other_states_resources(struct trident_state *state, 
+					       int chan_nums);
 static void ali_free_other_states_resources(struct trident_state *state);
 
 
@@ -450,22 +491,29 @@
 	unsigned mixer_regs[ALI_MIXER_REGS];
 } ali_registers;
 
-#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count)	(dma_ptr) += (offset);	\
-							(buffer) += (offset);	\
-							(cnt) -= (offset);	\
-							(copy_count) += (offset);
-
-#define lock_set_fmt(state)	{spin_lock_irqsave(&state->card->lock, flags);			\
-				if (state->fmt_flag) {						\
-					spin_unlock_irqrestore(&state->card->lock, flags);	\
-					return -EFAULT;						\
-				}								\
-				state->fmt_flag = 1;						\
-				spin_unlock_irqrestore(&state->card->lock, flags);}
+#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count)	do { \
+        (dma_ptr) += (offset);	  \
+	(buffer) += (offset);	  \
+        (cnt) -= (offset);	  \
+	(copy_count) += (offset); \
+} while (0)
+	  
+
+#define lock_set_fmt(state) do { \
+        spin_lock_irqsave(&state->card->lock, flags);			\
+	if (state->fmt_flag) {						\
+	       spin_unlock_irqrestore(&state->card->lock, flags);	\
+               return -EFAULT;					        \
+	}								\
+	state->fmt_flag = 1;						\
+	spin_unlock_irqrestore(&state->card->lock, flags);              \
+} while (0)
 				
-#define unlock_set_fmt(state)	{spin_lock_irqsave(&state->card->lock, flags);		\
-				state->fmt_flag = 0;					\
-				spin_unlock_irqrestore(&state->card->lock, flags);}
+#define unlock_set_fmt(state)  do {                             \
+        spin_lock_irqsave(&state->card->lock, flags);		\
+	state->fmt_flag = 0;					\
+	spin_unlock_irqrestore(&state->card->lock, flags);      \
+} while (0)
 
 static int trident_enable_loop_interrupts(struct trident_card * card)
 {
@@ -490,10 +538,9 @@
 
 	outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
 
-#ifdef DEBUG
-	printk("trident: Enable Loop Interrupts, globctl = 0x%08X\n",
-			inl(TRID_REG(card, T4D_LFO_GC_CIR)));
-#endif
+	TRDBG("trident: Enable Loop Interrupts, globctl = 0x%08X\n",
+	      inl(TRID_REG(card, T4D_LFO_GC_CIR)));
+
 	return (TRUE);
 }
 
@@ -505,10 +552,9 @@
 	global_control &= ~(ENDLP_IE | MIDLP_IE);
 	outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
 
-#ifdef DEBUG
-	printk("trident: Disabled Loop Interrupts, globctl = 0x%08X\n",
-	       global_control);
-#endif
+	TRDBG("trident: Disabled Loop Interrupts, globctl = 0x%08X\n",
+	      global_control);
+
 	return (TRUE);
 }
 
@@ -524,9 +570,9 @@
 
 #ifdef DEBUG
 	reg = inl(TRID_REG(card, addr));
-	printk("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
-		channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr);
-#endif
+	TRDBG("trident: enabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
+	      channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr);
+#endif /* DEBUG */ 
 }
 
 static void trident_disable_voice_irq(struct trident_card * card, unsigned int channel)
@@ -544,9 +590,9 @@
 
 #ifdef DEBUG
 	reg = inl(TRID_REG(card, addr));
-	printk("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
-		channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr);
-#endif
+	TRDBG("trident: disabled IRQ on channel %d, %s = 0x%08x(addr:%X)\n",
+	      channel, addr==T4D_AINTEN_B? "AINTEN_B":"AINTEN_A",reg,addr);
+#endif /* DEBUG */ 
 }
 
 static void trident_start_voice(struct trident_card * card, unsigned int channel)
@@ -557,15 +603,15 @@
 
 #ifdef DEBUG
 	u32 reg;
-#endif
+#endif /* DEBUG */ 
 
 	outl(mask, TRID_REG(card, addr));
 
-#ifdef DEBUG
+#ifdef DEBUG 
 	reg = inl(TRID_REG(card, addr));
-	printk("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n",
-		channel, addr==T4D_START_B? "START_B":"START_A",reg,addr);
-#endif
+	TRDBG("trident: start voice on channel %d, %s = 0x%08x(addr:%X)\n",
+	      channel, addr==T4D_START_B? "START_B":"START_A",reg,addr);
+#endif /* DEBUG */ 
 }
 
 static void trident_stop_voice(struct trident_card * card, unsigned int channel)
@@ -576,15 +622,15 @@
 
 #ifdef DEBUG
 	u32 reg;
-#endif
+#endif /* DEBUG */ 
 
 	outl(mask, TRID_REG(card, addr));
 
 #ifdef DEBUG
 	reg = inl(TRID_REG(card, addr));
-	printk("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n",
-		channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr);
-#endif
+	TRDBG("trident: stop voice on channel %d, %s = 0x%08x(addr:%X)\n",
+	      channel, addr==T4D_STOP_B? "STOP_B":"STOP_A",reg,addr);
+#endif /* DEBUG */ 
 }
 
 static u32 trident_get_interrupt_mask (struct trident_card * card, unsigned int channel)
@@ -601,9 +647,9 @@
 
 #ifdef DEBUG
 	if (reg & mask)
-		printk("trident: channel %d has interrupt, %s = 0x%08x\n",
-			channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg);
-#endif
+		TRDBG("trident: channel %d has interrupt, %s = 0x%08x\n",
+		      channel,reg==T4D_AINT_B? "AINT_B":"AINT_A", reg);
+#endif /* DEBUG */ 
 	return (reg & mask) ? TRUE : FALSE;
 }
 
@@ -619,9 +665,9 @@
 
 #ifdef DEBUG
 	reg = inl(TRID_REG(card, T4D_AINT_B));
-	printk("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n",
-	       channel, reg);
-#endif
+	TRDBG("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n",
+	      channel, reg);
+#endif /* DEBUG */ 
 }
 
 static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *card)
@@ -722,9 +768,8 @@
  	 *	Keep interrupts off for the configure - we don't want to
  	 *	clash with another cyberpro config event
  	 */
- 
-	save_flags(flags);
-	cli();
+ 	
+	spin_lock_irqsave(&card->lock, flags); 
 	portDat = cyber_inidx(CYBER_PORT_AUDIO, CYBER_IDX_AUDIO_ENABLE);
 	/* enable, if it was disabled */
 	if( (portDat & CYBER_BMSK_AUENZ) != CYBER_BMSK_AUENZ_ENABLE ) {
@@ -749,7 +794,7 @@
 		cyber_outidx( CYBER_PORT_AUDIO, 0xb3, 0x06 );
 		cyber_outidx( CYBER_PORT_AUDIO, 0xbf, 0x00 );
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags); 
 	return ret;
 }
 
@@ -869,9 +914,7 @@
 
 	trident_write_voice_regs(state);
 
-#ifdef DEBUG
-	printk("trident: called trident_set_dac_rate : rate = %d\n", rate);
-#endif
+	TRDBG("trident: called trident_set_dac_rate : rate = %d\n", rate);
 
 	return rate;
 }
@@ -891,9 +934,8 @@
 
 	trident_write_voice_regs(state);
 
-#ifdef DEBUG
-	printk("trident: called trident_set_adc_rate : rate = %d\n", rate);
-#endif
+	TRDBG("trident: called trident_set_adc_rate : rate = %d\n", rate);
+
 	return rate;
 }
 
@@ -935,11 +977,11 @@
 	if (dmabuf->fmt & TRIDENT_FMT_STEREO)
 		/* stereo */
 		channel->control |= CHANNEL_STEREO;
-#ifdef DEBUG
-	printk("trident: trident_play_setup, LBA = 0x%08x, "
-	       "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n",
-	       channel->lba, channel->delta, channel->eso, channel->control);
-#endif
+
+	TRDBG("trident: trident_play_setup, LBA = 0x%08x, "
+	      "Delta = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n",
+	      channel->lba, channel->delta, channel->eso, channel->control);
+
 	trident_write_voice_regs(state);
 }
 
@@ -1021,11 +1063,11 @@
 	if (dmabuf->fmt & TRIDENT_FMT_STEREO)
 		/* stereo */
 		channel->control |= CHANNEL_STEREO;
-#ifdef DEBUG
-	printk("trident: trident_rec_setup, LBA = 0x%08x, "
-	       "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n",
-	       channel->lba, channel->delta, channel->eso, channel->control);
-#endif
+	
+	TRDBG("trident: trident_rec_setup, LBA = 0x%08x, "
+	      "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n",
+	      channel->lba, channel->delta, channel->eso, channel->control);
+
 	trident_write_voice_regs(state);
 }
 
@@ -1058,11 +1100,10 @@
 		return 0;
 	}
 
-#ifdef DEBUG
-	printk("trident: trident_get_dma_addr: chip reported channel: %d, "
-	       "cso = 0x%04x\n",
-	       dmabuf->channel->num, cso);
-#endif
+	
+	TRDBG("trident: trident_get_dma_addr: chip reported channel: %d, "
+	      "cso = 0x%04x\n", dmabuf->channel->num, cso);
+
 	/* ESO and CSO are in units of Samples, convert to byte offset */
 	cso <<= sample_shift[dmabuf->fmt];
 
@@ -1160,27 +1201,18 @@
 #define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
-/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
-static int alloc_dmabuf(struct trident_state *state)
+/* alloc a DMA buffer of with a buffer of this order */ 
+static int alloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev, int order)
 {
-	struct dmabuf *dmabuf = &state->dmabuf;
 	void *rawbuf = NULL;
-	int order;
 	struct page *page, *pend;
 
-	/* alloc as big a chunk as we can, FIXME: is this necessary ?? */
-	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
-		if ((rawbuf = pci_alloc_consistent(state->card->pci_dev,
-						   PAGE_SIZE << order,
-						   &dmabuf->dma_handle)))
-			break;
-	if (!rawbuf)
+	if (!(rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
+					    &dmabuf->dma_handle)))
 		return -ENOMEM;
 
-#ifdef DEBUG
-	printk("trident: allocated %ld (order = %d) bytes at %p\n",
-	       PAGE_SIZE << order, order, rawbuf);
-#endif
+	TRDBG("trident: allocated %ld (order = %d) bytes at %p\n",
+	      PAGE_SIZE << order, order, rawbuf);
 
 	dmabuf->ready  = dmabuf->mapped = 0;
 	dmabuf->rawbuf = rawbuf;
@@ -1194,21 +1226,37 @@
 	return 0;
 }
 
-/* free DMA buffer */
-static void dealloc_dmabuf(struct trident_state *state)
+/* allocate the main DMA buffer, playback and recording buffer should be */ 
+/* allocated seperately */
+static int alloc_main_dmabuf(struct trident_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
-	struct page *page, *pend;
+	int order;
+	int ret = -ENOMEM; 
 
+	/* alloc as big a chunk as we can, FIXME: is this necessary ?? */
+	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) {
+		if (!(ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order)))
+			return 0; 
+		/* else try again */ 
+	}
+	return ret; 
+}
+
+/* deallocate a DMA buffer */ 
+static void dealloc_dmabuf(struct dmabuf* dmabuf, struct pci_dev* pci_dev)
+{
+	struct page *page, *pend;
+	
 	if (dmabuf->rawbuf) {
 		/* undo marking the pages as reserved */
 		pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
 		for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
 			mem_map_unreserve(page);
-		pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder,
+		pci_free_consistent(pci_dev, PAGE_SIZE << dmabuf->buforder,
 				    dmabuf->rawbuf, dmabuf->dma_handle);
+		dmabuf->rawbuf = NULL;
 	}
-	dmabuf->rawbuf = NULL;
 	dmabuf->mapped = dmabuf->ready = 0;
 }
 
@@ -1220,16 +1268,16 @@
 	unsigned bufsize, dma_nums;
 	unsigned long flags;
 	int ret, i, order;
-	struct page *page, *pend;
 	
 	lock_set_fmt(state);
 	if (state->chans_num == 6)
 		dma_nums = 5;
-	else 	dma_nums = 1;
+	else 	
+		dma_nums = 1;
 	
 	for (i = 0; i < dma_nums; i++) {
 		if (i > 0) {
-			s = state->other_states[i - 1];			
+			s = state->other_states[i - 1];
 			dmabuf = &s->dmabuf;
 			dmabuf->fmt = state->dmabuf.fmt;
 			dmabuf->rate = state->dmabuf.rate;
@@ -1243,35 +1291,25 @@
 		/* allocate DMA buffer if not allocated yet */
 		if (!dmabuf->rawbuf) {
 			if (i == 0) {
-				if ((ret = alloc_dmabuf(state))) {
+				if ((ret = alloc_main_dmabuf(state))) {
 					unlock_set_fmt(state);
 					return ret;
 				}
-			}
-			else {
+			} else {
+				ret = -ENOMEM; 
 				if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) {
-					dmabuf->rawbuf = pci_alloc_consistent(state->card->pci_dev,
-									      PAGE_SIZE << order,
-									      &dmabuf->dma_handle);
+					ret = alloc_dmabuf(dmabuf, state->card->pci_dev, order); 
 				}
-				if (!dmabuf->rawbuf) {
-					free_pages((unsigned long)state->dmabuf.rawbuf, state->dmabuf.buforder);
-					state->dmabuf.rawbuf = NULL;
-					i-=2;
-					for (; i >= 0; i--) {
-						pci_free_consistent(state->card->pci_dev,
-								    PAGE_SIZE << state->other_states[i]->dmabuf.buforder,
-								    state->other_states[i]->dmabuf.rawbuf,
-								    state->other_states[i]->dmabuf.dma_handle);
-					}
+				if (ret) {
+					/* release the main DMA buffer */ 
+					dealloc_dmabuf(&state->dmabuf, state->card->pci_dev); 
+					/* release the auxiliary DMA buffers */ 
+					for (i-=2; i >= 0; i--)
+						dealloc_dmabuf(&state->other_states[i]->dmabuf, 
+							       state->card->pci_dev); 
 					unlock_set_fmt(state);
-					return -ENOMEM;
+					return ret; 
 				}
-				dmabuf->ready  = dmabuf->mapped = 0;
-				dmabuf->buforder = order;
-				pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << order) - 1);
-				for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++)
-					mem_map_reserve(page);
 			}
 		}
 		/* FIXME: figure out all this OSS fragment stuff */
@@ -1301,22 +1339,20 @@
 		       dmabuf->dmasize);
 
 		spin_lock_irqsave(&s->card->lock, flags);
-		if (rec) {
+		if (rec) 
 			trident_rec_setup(s);
-		} else {
+		else 
 			trident_play_setup(s);
-		}
+		
 		spin_unlock_irqrestore(&s->card->lock, flags);
 
 		/* set the ready flag for the dma buffer */
 		dmabuf->ready = 1;
 
-#ifdef DEBUG
-	printk("trident: prog_dmabuf(%d), sample rate = %d, format = %d, numfrag = %d, "
-	       "fragsize = %d dmasize = %d\n",
-	       dmabuf->channel->num, dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
-	       dmabuf->fragsize, dmabuf->dmasize);
-#endif
+		TRDBG("trident: prog_dmabuf(%d), sample rate = %d, format = %d, numfrag = %d, "
+		      "fragsize = %d dmasize = %d\n",
+		      dmabuf->channel->num, dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
+		      dmabuf->fragsize, dmabuf->dmasize);
 	}
 	unlock_set_fmt(state);
 	return 0;
@@ -1540,19 +1576,21 @@
 {
 	int i;
 	struct trident_state *state;
+	unsigned int channel; 
 	
 	/* Update the pointers for all channels we are running. */
 	/* FIXME: should read interrupt status only once */
 	for (i = 0; i < NR_HW_CH; i++) {
-		if (trident_check_channel_interrupt(card, 63 - i)) {
-			trident_ack_channel_interrupt(card, 63 - i);
+		channel = 63 - i; 
+		if (trident_check_channel_interrupt(card, channel)) {
+			trident_ack_channel_interrupt(card, channel);
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk("trident: spurious channel irq %d.\n",
-				       63 - i);
-				trident_stop_voice(card, 63 - i);
-				trident_disable_voice_irq(card, 63 - i);
+				printk(KERN_WARNING "trident: spurious channel "
+				       "irq %d.\n", channel);
+				trident_stop_voice(card, channel);
+				trident_disable_voice_irq(card, channel);
 			}
 		}
 	}
@@ -1660,29 +1698,29 @@
 {
 	int i,irq_status;
 	struct trident_state *state;
+	unsigned int channel; 
 
 	/* Update the pointers for all channels we are running. */
 	/* FIXED: read interrupt status only once */
 	irq_status=inl(TRID_REG(card, T4D_AINT_A) );
-#ifdef DEBUG	
-	printk("cyber_address_interrupt: irq_status 0x%X\n",irq_status);
-#endif
-	for (i = 0; i < NR_HW_CH; i++) {
-		if (irq_status & ( 1 << (31 - i)) ) {
 
+	TRDBG("cyber_address_interrupt: irq_status 0x%X\n",irq_status);
+
+	for (i = 0; i < NR_HW_CH; i++) {
+		channel = 31 - i; 
+		if (irq_status & ( 1 << channel) ) {
 			/* clear bit by writing a 1, zeroes are ignored */ 		
-			outl( (1 <<(31-i)), TRID_REG(card, T4D_AINT_A));
+			outl( (1 << channel), TRID_REG(card, T4D_AINT_A));
 		
-#ifdef DEBUG	
-	printk("cyber_interrupt: channel %d\n", 31-i);
-#endif
+			TRDBG("cyber_interrupt: channel %d\n", channel);
+
 			if ((state = card->states[i]) != NULL) {
 				trident_update_ptr(state);
 			} else {
-				printk("cyber5050: spurious channel irq %d.\n",
-				       31 - i);
-				trident_stop_voice(card, 31 - i);
-				trident_disable_voice_irq(card, 31 - i);
+				printk(KERN_WARNING "cyber5050: spurious "
+				       "channel irq %d.\n", channel); 
+				trident_stop_voice(card, channel);
+				trident_disable_voice_irq(card, channel);
 			}
 		}
 	}
@@ -1697,9 +1735,7 @@
 	spin_lock(&card->lock);
 	event = inl(TRID_REG(card, T4D_MISCINT));
 
-#ifdef DEBUG
-	printk("trident: trident_interrupt called, MISCINT = 0x%08x\n", event);
-#endif
+	TRDBG("trident: trident_interrupt called, MISCINT = 0x%08x\n", event);
 
 	if (event & ADDRESS_IRQ) {
 		card->address_interrupt(card);
@@ -1737,9 +1773,7 @@
 	unsigned swptr;
 	int cnt;
 
-#ifdef DEBUG
-	printk("trident: trident_read called, count = %d\n", count);
-#endif
+	TRDBG("trident: trident_read called, count = %d\n", count);
 
 	VALIDATE_STATE(state);
 	if (ppos != &file->f_pos)
@@ -1793,12 +1827,11 @@
 			   which results in a (potential) buffer overrun. And worse, there is
 			   NOTHING we can do to prevent it. */
 			if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-#ifdef DEBUG
-				printk(KERN_ERR "trident: recording schedule timeout, "
-				       "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-				       dmabuf->hwptr, dmabuf->swptr);
-#endif
+				TRDBG(KERN_ERR "trident: recording schedule timeout, "
+				      "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+				      dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
+				      dmabuf->hwptr, dmabuf->swptr);
+
 				/* a buffer overrun, we delay the recovery until next time the
 				   while loop begin and we REALLY have space to record */
 			}
@@ -1852,9 +1885,8 @@
 	unsigned int state_cnt;
 	unsigned int copy_count;
 
-#ifdef DEBUG
-	printk("trident: trident_write called, count = %d\n", count);
-#endif
+	TRDBG("trident: trident_write called, count = %d\n", count);
+
 	VALIDATE_STATE(state);
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
@@ -1922,12 +1954,11 @@
 			   which results in a (potential) buffer underrun. And worse, there is
 			   NOTHING we can do to prevent it. */
 			if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
-#ifdef DEBUG
-				printk(KERN_ERR "trident: playback schedule timeout, "
-				       "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
-				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
-				       dmabuf->hwptr, dmabuf->swptr);
-#endif
+				TRDBG(KERN_ERR "trident: playback schedule timeout, "
+				      "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+				      dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
+				      dmabuf->hwptr, dmabuf->swptr);
+
 				/* a buffer underrun, we delay the recovery until next time the
 				   while loop begin and we REALLY have data to play */
 			}
@@ -2106,10 +2137,8 @@
 	VALIDATE_STATE(state);
 	mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) ||
 		((file->f_mode & FMODE_READ) && dmabuf->mapped);
-#ifdef DEBUG
-	printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",
-	       _IOC_NR(cmd), arg ? *(int *)arg : 0);
-#endif
+	TRDBG("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",
+	      _IOC_NR(cmd), arg ? *(int *)arg : 0);
 
 	switch (cmd) 
 	{
@@ -2269,6 +2298,7 @@
 						{
 							printk(KERN_ERR "trident: Record is working on the card!\n");
 							ret = -EBUSY;
+							unlock_set_fmt(state); 
 							break;
 						}
 
@@ -2454,8 +2484,7 @@
 		if (dmabuf->mapped)
 			dmabuf->count &= dmabuf->fragsize-1;
 		spin_unlock_irqrestore(&state->card->lock, flags);
-		ret = copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ?
-				-EFAULT : 0;
+		ret = copy_to_user((void *)arg, &cinfo, sizeof(cinfo))?-EFAULT:0;
 		break;
 
 	case SNDCTL_DSP_GETOPTR:
@@ -2673,10 +2702,8 @@
 	state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 	up(&card->open_sem);
 
-#ifdef DEBUG
-       printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", 
+	TRDBG("trident: open virtual channel %d, hard channel %d\n", 
               state->virt, dmabuf->channel->num);
-#endif
 
 	return 0;
 }
@@ -2686,7 +2713,6 @@
 	struct trident_state *state = (struct trident_state *)file->private_data;
 	struct trident_card *card;
 	struct dmabuf *dmabuf;
-	unsigned long flags;
 
 	lock_kernel();
 	card = state->card;
@@ -2698,20 +2724,15 @@
 		drain_dac(state, file->f_flags & O_NONBLOCK);
 	}
 
-#ifdef DEBUG
-	printk(KERN_ERR "trident: closing virtual channel %d, hard channel %d\n", 
-		state->virt, dmabuf->channel->num);
-#endif
+	TRDBG("trident: closing virtual channel %d, hard channel %d\n", 
+	      state->virt, dmabuf->channel->num);
 
 	/* stop DMA state machine and free DMA buffers/channels */
 	down(&card->open_sem);
 
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac(state);
-		lock_set_fmt(state);
-
-		unlock_set_fmt(state);
-		dealloc_dmabuf(state);
+		dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 
 		/* Added by Matt Wu */
@@ -2727,7 +2748,7 @@
 	}
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(state);
-		dealloc_dmabuf(state);
+		dealloc_dmabuf(&state->dmabuf, state->card->pci_dev);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 
 		/* Added by Matt Wu */
@@ -2876,62 +2897,74 @@
 	return ((u16) (data >> 16));
 }
 
-/* Write AC97 codec registers for ALi*/
-static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
+/* rewrite ac97 read and write mixer register by hulei for ALI*/
+static int acquirecodecaccess(struct trident_card *card)
 {
-	unsigned int address, mask;
-	unsigned int wCount1 = 0xffff;
-	unsigned int wCount2= 0xffff;
-	unsigned long chk1, chk2;
-	unsigned long flags;
-	u32 data;
-
-	data = ((u32) val) << 16;
-
-	if(!card)
-		BUG();
-		
-	address = ALI_AC97_WRITE;
-	mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
-	if (secondary)
-		mask |= ALI_AC97_SECONDARY;
-	if (card->revision == ALI_5451_V02)
-		mask |= ALI_AC97_WRITE_MIXER_REGISTER;
+	u16 wsemamask=0x6000; /* bit 14..13 */
+	u16 wsemabits;
+        u16 wcontrol ;
+	int block = 0;
+	int ncount = 25;
+	while (1) {
+		wcontrol = inw(TRID_REG(card,  ALI_AC97_WRITE));
+		wsemabits = wcontrol & wsemamask;
 		
-	spin_lock_irqsave(&card->lock, flags);
-	while (wCount1--) {
-		if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_WRITE) == 0) {
-			data |= (mask | (reg & AC97_REG_ADDR));
-			
-			chk1 = inl(TRID_REG(card,  ALI_STIMER));
-			chk2 = inl(TRID_REG(card,  ALI_STIMER));
-			while (wCount2-- && (chk1 == chk2))
-				chk2 = inl(TRID_REG(card,  ALI_STIMER));
-			if (wCount2 == 0) {
-				spin_unlock_irqrestore(&card->lock, flags);
-				return;
-			}
-			outl(data, TRID_REG(card, address));	//write!
-			spin_unlock_irqrestore(&card->lock, flags);
-			return;	//success
+		if (wsemabits==0x4000)
+			return 1; /* 0x4000 is audio ,then success */
+		if (ncount-- < 0)
+			break;
+		if (wsemabits == 0)
+		{
+		unlock:
+			outl(((u32)(wcontrol & 0x1eff)|0x00004000), TRID_REG(card, ALI_AC97_WRITE));
+			continue;
 		}
-		inw(TRID_REG(card, address));	//wait for a read cycle
+		udelay(20);
+	}
+	if(!block)
+	{
+		TRDBG("accesscodecsemaphore: try unlock\n");
+		block = 1;
+		goto unlock;
 	}
+	printk(KERN_ERR "accesscodecsemaphore: fail\n");
+	return 0;
+}
 
-	printk(KERN_ERR "ali: AC97 CODEC write timed out.\n");
-	spin_unlock_irqrestore(&card->lock, flags);
-	return;
+static void releasecodecaccess(struct trident_card *card)
+{ 
+	unsigned long wcontrol;
+	wcontrol = inl(TRID_REG(card,  ALI_AC97_WRITE));
+	outl((wcontrol & 0xffff1eff), TRID_REG(card, ALI_AC97_WRITE));
+}
+
+static int waitforstimertick(struct trident_card *card)
+{
+	unsigned long chk1, chk2;
+	unsigned int wcount = 0xffff;
+	chk1 = inl(TRID_REG(card,  ALI_STIMER));
+	
+	while(1) {
+		chk2 = inl(TRID_REG(card,  ALI_STIMER));
+		if( (wcount > 0) && chk1 != chk2)
+			return 1;
+		if(wcount <= 0)
+			break;
+		udelay(50);
+	}
+
+	printk(KERN_NOTICE "waitforstimertick :BIT_CLK is dead\n");
+	return 0;
 }
 
 /* Read AC97 codec registers for ALi*/
 static u16 ali_ac97_get(struct trident_card *card, int secondary, u8 reg)
 {
 	unsigned int address, mask;
-        unsigned int wCount1 = 0xffff;
-        unsigned int wCount2= 0xffff;
-        unsigned long chk1, chk2;
-	unsigned long flags;
+	unsigned int ncount;
+        unsigned long aud_reg;
 	u32 data;
+        u16 wcontrol;
 
 	if(!card)
 		BUG();
@@ -2943,37 +2976,102 @@
 	mask = ALI_AC97_READ_ACTION | ALI_AC97_AUDIO_BUSY;
 	if (secondary)
 		mask |= ALI_AC97_SECONDARY;
+    
+	if (!acquirecodecaccess(card))
+		printk(KERN_ERR "access codec fail\n");
+	
+	wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
+	wcontrol &= 0xfe00;
+	wcontrol |= (0x8000|reg);
+	outw(wcontrol,TRID_REG(card,  ALI_AC97_WRITE));
 
-	spin_lock_irqsave(&card->lock, flags);
 	data = (mask | (reg & AC97_REG_ADDR));
-	while (wCount1--) {
-		if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) {
-			chk1 = inl(TRID_REG(card,  ALI_STIMER));
-			chk2 = inl(TRID_REG(card,  ALI_STIMER));
-			while (wCount2-- && (chk1 == chk2))
-				chk2 = inl(TRID_REG(card,  ALI_STIMER));
-			if (wCount2 == 0) {
-				printk(KERN_ERR "ali: AC97 CODEC read timed out.\n");
-				spin_unlock_irqrestore(&card->lock, flags);
-				return 0;
-			}
-			outl(data, TRID_REG(card, address));	//read!
-			wCount2 = 0xffff;
-			while (wCount2--) {
-				if ((inw(TRID_REG(card, address)) & ALI_AC97_BUSY_READ) == 0) {
-					data = inl(TRID_REG(card, address));
-					spin_unlock_irqrestore(&card->lock, flags);
-					return ((u16) (data >> 16));
-				}
-			}
+	
+	if(!waitforstimertick(card)) {
+		printk(KERN_ERR "BIT_CLOCK is dead\n");
+		goto releasecodec;
+	}
+	
+	udelay(20);		
+	
+	ncount=10;
+	
+	while(1) {
+		if ((inw(TRID_REG(card,ALI_AC97_WRITE)) & ALI_AC97_BUSY_READ) != 0)
+			break;
+		if(ncount <=0)
+			break;
+		if(ncount--==1) {
+			TRDBG("ali_ac97_read :try clear busy flag\n");
+			aud_reg = inl(TRID_REG(card,  ALI_AC97_WRITE));
+			outl((aud_reg & 0xffff7fff), TRID_REG(card, ALI_AC97_WRITE));
 		}
-		inw(TRID_REG(card, address));	//wait a read cycle
+		udelay(10);
 	}
-	spin_unlock_irqrestore(&card->lock, flags);
+	
+	data = inl(TRID_REG(card, address));
+	
+	return ((u16) (data >> 16));
+
+ releasecodec: 
+	releasecodecaccess(card);
 	printk(KERN_ERR "ali: AC97 CODEC read timed out.\n");
 	return 0;
 }
 
+
+/* Write AC97 codec registers for hulei*/
+static void ali_ac97_set(struct trident_card *card, int secondary, u8 reg, u16 val)
+{
+	unsigned int address, mask;
+	unsigned int ncount;
+	u32 data;
+        u16 wcontrol;
+	
+	data = ((u32) val) << 16;
+	
+	if(!card)
+		BUG();
+	
+	address = ALI_AC97_WRITE;
+	mask = ALI_AC97_WRITE_ACTION | ALI_AC97_AUDIO_BUSY;
+	if (secondary)
+		mask |= ALI_AC97_SECONDARY;
+	if (card->revision == ALI_5451_V02)
+		mask |= ALI_AC97_WRITE_MIXER_REGISTER;
+		
+        if (!acquirecodecaccess(card))      
+		printk(KERN_ERR "access codec fail\n");
+			
+	wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
+	wcontrol &= 0xff00;
+	wcontrol |= (0x8100|reg);/* bit 8=1: (ali1535 )reserved /ali1535+ write */
+	outl(( data |wcontrol), TRID_REG(card,ALI_AC97_WRITE ));
+
+        if(!waitforstimertick(card)) {
+		printk(KERN_ERR "BIT_CLOCK is dead\n");
+		goto releasecodec;
+	}
+	
+        ncount = 10;
+	while(1) {
+		wcontrol = inw(TRID_REG(card, ALI_AC97_WRITE));
+		if(!wcontrol & 0x8000)
+			break;
+		if(ncount <= 0)
+			break;
+		if(ncount-- == 1) {
+			TRDBG("ali_ac97_set :try clear busy flag!!\n");
+			outw(wcontrol & 0x7fff, TRID_REG(card, ALI_AC97_WRITE));
+		}
+		udelay(10);
+	}
+	
+ releasecodec:
+	releasecodecaccess(card);
+	return;
+}
+
 static void ali_enable_special_channel(struct trident_state *stat)
 {
 	struct trident_card *card = stat->card;
@@ -3305,11 +3403,18 @@
 			ali_ac97_write(card->ac97_codec[0], 0x02, 8080);
 			ali_ac97_write(card->ac97_codec[0], 0x36, 0);
 			ali_ac97_write(card->ac97_codec[0], 0x38, 0);
-			ali_ac97_write(card->ac97_codec[1], 0x36, 0);
-			ali_ac97_write(card->ac97_codec[1], 0x38, 0);
-			ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606);
-			ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303);
-			ali_ac97_write(card->ac97_codec[1], 0x74, 0x3);
+			/*
+			 *	On a board with a single codec you won't get the
+			 *	surround. On other boards configure it.
+			 */
+			if(card->ac97_codec[1]!=NULL)
+			{
+				ali_ac97_write(card->ac97_codec[1], 0x36, 0);
+				ali_ac97_write(card->ac97_codec[1], 0x38, 0);
+				ali_ac97_write(card->ac97_codec[1], 0x02, 0x0606);
+				ali_ac97_write(card->ac97_codec[1], 0x18, 0x0303);
+				ali_ac97_write(card->ac97_codec[1], 0x74, 0x3);
+			}
 			return 1;
 		}
 	}
@@ -3396,9 +3501,8 @@
 	unsigned long flags;
 	int i, j;
 
-	save_flags(flags); 
-	cli();
-	
+	spin_lock_irqsave(&card->lock, flags); 
+
 	ali_registers.global_regs[0x2c] = inl(TRID_REG(card,T4D_MISCINT));
 	//ali_registers.global_regs[0x20] = inl(TRID_REG(card,T4D_START_A));	
 	ali_registers.global_regs[0x21] = inl(TRID_REG(card,T4D_STOP_A));
@@ -3426,7 +3530,7 @@
 	//Stop all HW channel
 	outl(ALI_STOP_ALL_CHANNELS, TRID_REG(card, T4D_STOP_A));
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags); 
 }
 
 static void ali_restore_regs(struct trident_card *card)
@@ -3434,8 +3538,7 @@
 	unsigned long flags;
 	int i, j;
 
-	save_flags(flags); 
-	cli();
+	spin_lock_irqsave(&card->lock, flags); 
 	
 	for (i = 1; i < ALI_MIXER_REGS; i++)
 		ali_ac97_write(card->ac97_codec[0], i*2, ali_registers.mixer_regs[i]);
@@ -3458,13 +3561,13 @@
 	outl(ali_registers.global_regs[0x20], TRID_REG(card,T4D_START_A));
 	//restore IRQ enable bits
 	outl(ali_registers.global_regs[0x2c], TRID_REG(card,T4D_MISCINT));
-	
-	restore_flags(flags);
+
+	spin_unlock_irqrestore(&card->lock, flags); 
 }
 
 static int trident_suspend(struct pci_dev *dev, u32 unused)
 {
-	struct trident_card *card = (struct trident_card *) dev;
+	struct trident_card *card = pci_get_drvdata(dev); 
 
 	if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
 		ali_save_regs(card);
@@ -3474,7 +3577,7 @@
 
 static int trident_resume(struct pci_dev *dev)
 {
-	struct trident_card *card = (struct trident_card *) dev;
+	struct trident_card *card = pci_get_drvdata(dev); 
 
 	if(card->pci_id == PCI_DEVICE_ID_ALI_5451) {
 		ali_restore_regs(card);
@@ -3601,7 +3704,10 @@
 depend on a master state's DMA, and changing the counters of the master
 state DMA is protected by a spinlock.
 */
-static int ali_write_5_1(struct trident_state *state,  const char *buf, int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt)
+static int ali_write_5_1(struct trident_state *state,  
+			 const char *buf, int cnt_for_multi_channel, 
+			 unsigned int *copy_count, 
+			 unsigned int *state_cnt)
 {
 	
 	struct dmabuf *dmabuf = &state->dmabuf;
@@ -3707,7 +3813,7 @@
 	other_states_count = state->chans_num - 2;	/* except PCM L/R channels*/
 	for ( i = 0; i < other_states_count; i++) {
 		s = state->other_states[i];
-		dealloc_dmabuf(s);
+		dealloc_dmabuf(&s->dmabuf, card->pci_dev);
 		ali_disable_special_channel(s->card, s->dmabuf.channel->num);
 		state->card->free_pcm_channel(s->card, s->dmabuf.channel->num);
 		card->states[s->virt] = NULL;
@@ -3715,7 +3821,6 @@
 	}
 }
 
-#ifdef CONFIG_PROC_FS
 struct proc_dir_entry *res;
 static int ali_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
 {
@@ -3753,7 +3858,6 @@
 
 	return count;
 }
-#endif
 
 /* OSS /dev/mixer file operation methods */
 static int trident_open_mixdev(struct inode *inode, struct file *file)
@@ -3821,7 +3925,7 @@
 	pci_write_config_dword(pci_dev, 0x44, dwVal & 0xfffbffff);
 	udelay(5000);
 
-	wCount = 200;
+	wCount = 2000;
 	while(wCount--) {
 		wReg = ali_ac97_get(card, 0, AC97_POWER_CONTROL);
 		if((wReg & 0x000f) == 0x000f)
@@ -4087,13 +4191,11 @@
 		/* ALi SPDIF OUT function */
 		if(card->revision == ALI_5451_V02) {
 			ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);		
-#ifdef CONFIG_PROC_FS
 			res = create_proc_entry("ALi5451", 0, NULL);
 			if (res) {
 				res->write_proc = ali_write_proc;
 				res->data = card;
 			}
-#endif
 		}
 
 		/* Add H/W Volume Control By Matt Wu Jul. 06, 2001 */
@@ -4186,7 +4288,7 @@
 				ali_ac97_set(card, 0, AC97_POWER_CONTROL, ac97_data | ALI_EAPD_POWER_DOWN);
 			}
 		}
-#endif
+#endif /* CONFIG_ALPHA_NAUTILUS || CONFIG_ALPHA_GENERIC */ 
 		/* edited by HMSEO for GT sound*/
 	}
 	rc = 0;
@@ -4204,12 +4306,10 @@
 out_free_irq:
 	free_irq(card->irq, card);
 out_proc_fs:
-#ifdef CONFIG_PROC_FS
 	if (res) {
 		remove_proc_entry("ALi5451", NULL);
 		res = NULL;
 	}
-#endif
 	kfree(card);
 	devs = NULL;
 out_release_region:
@@ -4234,9 +4334,7 @@
 		ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
                 ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
                 ali_disable_spdif_in(card);
-#ifdef CONFIG_PROC_FS
 		remove_proc_entry("ALi5451", NULL);
-#endif
 	}
 
 	/* Unregister gameport */
@@ -4283,8 +4381,9 @@
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
 
-	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro 5050 PCI Audio, version "
-	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "Trident 4DWave/SiS 7018/ALi 5451,Tvia CyberPro "
+	       "5050 PCI Audio, version " DRIVER_VERSION ", " 
+	       __TIME__ " " __DATE__ "\n");
 
 	if (!pci_register_driver(&trident_pci_driver)) {
 		pci_unregister_driver(&trident_pci_driver);
diff -Nru a/sound/oss/trident.h b/sound/oss/trident.h
--- a/sound/oss/trident.h	Thu Aug  1 14:17:36 2002
+++ b/sound/oss/trident.h	Thu Aug  1 14:17:36 2002
@@ -360,5 +360,16 @@
 	return r;
 }
 
-#endif /* __TRID4DWAVE_H */
+#ifdef DEBUG
+
+#define TRDBG(msg, args...) do {          \
+        printk(KERN_DEBUG msg , ##args ); \
+} while (0)
+
+#else /* !defined(DEBUG) */ 
 
+#define TRDBG(msg, args...) do { } while (0)
+
+#endif /* DEBUG */ 
+
+#endif /* __TRID4DWAVE_H */
diff -Nru a/sound/sound_core.c b/sound/sound_core.c
--- a/sound/sound_core.c	Thu Aug  1 14:17:40 2002
+++ b/sound/sound_core.c	Thu Aug  1 14:17:40 2002
@@ -554,14 +554,13 @@
 {
 	/* We have nothing to really do here - we know the lists must be
 	   empty */
-	devfs_unregister_chrdev(SOUND_MAJOR, "sound");
+	unregister_chrdev(SOUND_MAJOR, "sound");
 	devfs_unregister (devfs_handle);
 }
 
 static int __init init_soundcore(void)
 {
-	if(devfs_register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1)
-	{
+	if (register_chrdev(SOUND_MAJOR, "sound", &soundcore_fops)==-1) {
 		printk(KERN_ERR "soundcore: sound device already in use.\n");
 		return -EBUSY;
 	}
