diff -Nru a/Documentation/filesystems/devfs/ChangeLog b/Documentation/filesystems/devfs/ChangeLog
--- a/Documentation/filesystems/devfs/ChangeLog	Thu Aug  1 01:08:12 2002
+++ b/Documentation/filesystems/devfs/ChangeLog	Thu Aug  1 01:08:12 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/mmio_barrier.txt b/Documentation/mmio_barrier.txt
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/mmio_barrier.txt	Thu Aug  1 01:08:13 2002
@@ -0,0 +1,15 @@
+On some platforms, so-called memory-mapped I/O is weakly ordered.  For
+example, the following might occur:
+
+CPU A writes 0x1 to Device #1
+CPU B writes 0x2 to Device #1
+Device #1 sees 0x2
+Device #1 sees 0x1
+
+On such platforms, driver writers are responsible for ensuring that I/O
+writes to memory-mapped addresses on their device arrive in the order
+intended.  The mmiob() macro is provided for this purpose.  A typical use
+of this macro might be immediately prior to the exit of a critical
+section of code proteced by spinlocks.  This would ensure that subsequent
+writes to I/O space arrived only after all prior writes (much like a
+typical memory barrier op, mb(), only with respect to I/O).
diff -Nru a/Documentation/serial/driver b/Documentation/serial/driver
--- a/Documentation/serial/driver	Thu Aug  1 01:08:12 2002
+++ b/Documentation/serial/driver	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/Documentation/sysctl/vm.txt	Thu Aug  1 01:08:13 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 01:08:13 2002
@@ -0,0 +1,70 @@
+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)
+
+	WRITABLE SHARED		-	size of mapping per instance
+
+For a direct map
+	SHARED or READ only	-	size of mapping
+	PRIVATE WRITEABLE	-	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)
+o	Account for shared anonymous mappings properly
+	- right now we account them per instance
diff -Nru a/Makefile b/Makefile
--- a/Makefile	Thu Aug  1 01:08:12 2002
+++ b/Makefile	Thu Aug  1 01:08:12 2002
@@ -221,7 +221,7 @@
 
 CPPFLAGS := -D__KERNEL__ -I$(HPATH)
 
-CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
+CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -g -O2 \
 	  -fomit-frame-pointer -fno-strict-aliasing -fno-common
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
 
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	Thu Aug  1 01:08:13 2002
+++ b/arch/arm/kernel/calls.S	Thu Aug  1 01:08:13 2002
@@ -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 01:08:12 2002
+++ b/arch/arm/kernel/entry-armv.S	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/kernel/entry-common.S	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/arm/kernel/entry-header.S	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/arm/kernel/irq.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/kernel/ptrace.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/arm/lib/kbd.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/arm/mach-integrator/cpu.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/adsbitsy.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/assabet.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/badge4.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/cpu-sa1100.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/cpu-sa1110.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/freebird.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/generic.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/arm/mach-sa1100/graphicsmaster.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/h3600.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/arm/mach-sa1100/huw_webpanel.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/arm/mach-sa1100/neponset.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/omnimeter.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/pfs168.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/arm/mach-sa1100/sa1111.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/arm/mach-sa1100/system3.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/arm/mach-sa1100/yopy.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mm/alignment.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/arm/mm/init.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/arm/mm/mm-armv.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/arm/tools/mach-types	Thu Aug  1 01:08:13 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/apm.c b/arch/i386/kernel/apm.c
--- a/arch/i386/kernel/apm.c	Thu Aug  1 01:08:12 2002
+++ b/arch/i386/kernel/apm.c	Thu Aug  1 01:08:12 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/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	Thu Aug  1 01:08:13 2002
+++ b/arch/i386/kernel/i8259.c	Thu Aug  1 01:08:13 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/irq.c b/arch/i386/kernel/irq.c
--- a/arch/i386/kernel/irq.c	Thu Aug  1 01:08:12 2002
+++ b/arch/i386/kernel/irq.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/i386/kernel/process.c	Thu Aug  1 01:08:12 2002
@@ -675,6 +675,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 +698,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 +831,27 @@
 /*
  * 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 +859,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/fault.c b/arch/i386/mm/fault.c
--- a/arch/i386/mm/fault.c	Thu Aug  1 01:08:12 2002
+++ b/arch/i386/mm/fault.c	Thu Aug  1 01:08:12 2002
@@ -28,8 +28,6 @@
 
 extern void die(const char *,struct pt_regs *,long);
 
-extern int console_loglevel;
-
 /*
  * Ugly, ugly, but the goto's result in better assembly..
  */
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	Thu Aug  1 01:08:12 2002
+++ b/arch/i386/mm/init.c	Thu Aug  1 01:08:12 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/Makefile b/arch/ia64/Makefile
--- a/arch/ia64/Makefile	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/Makefile	Thu Aug  1 01:08:12 2002
@@ -13,7 +13,7 @@
 
 export AWK
 
-OBJCOPYFLAGS := --strip-all 
+OBJCOPYFLAGS := --strip-all
 LDFLAGS_vmlinux := -static -T arch/$(ARCH)/vmlinux.lds
 AFLAGS_KERNEL := -mconstant-gp
 EXTRA	=
@@ -26,7 +26,7 @@
 GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.')
 
 ifneq ($(GCC_VERSION),2)
-	CFLAGS += -frename-registers --param max-inline-insns=2000
+	CFLAGS += -frename-registers --param max-inline-insns=5000
 endif
 
 ifeq ($(CONFIG_ITANIUM_BSTEP_SPECIFIC),y)
diff -Nru a/arch/ia64/boot/Makefile b/arch/ia64/boot/Makefile
--- a/arch/ia64/boot/Makefile	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/boot/Makefile	Thu Aug  1 01:08:13 2002
@@ -12,8 +12,10 @@
 
 OBJECTS	= bootloader.o
 
-targets-$(CONFIG_IA64_HP_SIM) += bootloader
-targets-$(CONFIG_IA64_GENERIC) += bootloader
+targets-$(CONFIG_IA64_HP_SIM)	+= bootloader
+targets-$(CONFIG_IA64_GENERIC)	+= bootloader
+
+CFLAGS	:= $(CFLAGS) $(CFLAGS_KERNEL)
 
 all:	$(targets-y)
 
diff -Nru a/arch/ia64/config.in b/arch/ia64/config.in
--- a/arch/ia64/config.in	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/config.in	Thu Aug  1 01:08:13 2002
@@ -64,12 +64,13 @@
 	fi
 fi
 
-if [ "$CONFIG_IA64_GENERIC" = "y" -o  "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ]; then
+if [ "$CONFIG_IA64_GENERIC" = "y" -o "$CONFIG_IA64_DIG" = "y" -o "$CONFIG_IA64_HP_ZX1" = "y" ];
+then
 	bool '  Enable IA-64 Machine Check Abort' CONFIG_IA64_MCA
 	define_bool CONFIG_PM y
 fi
 
-if [ "$CONFIG_IA64_SGI_SN1" = "y" -o  "$CONFIG_IA64_SGI_SN2" = "y" ]; then
+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 SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
@@ -99,21 +100,20 @@
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+  source drivers/acpi/Config.in
 
-source drivers/acpi/Config.in
+  bool 'PCI support' CONFIG_PCI
+  source drivers/pci/Config.in
 
-bool 'PCI support' CONFIG_PCI
-source drivers/pci/Config.in
-
-bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
-if [ "$CONFIG_HOTPLUG" = "y" ]; then
-   source drivers/pcmcia/Config.in
-else
-   define_bool CONFIG_PCMCIA n
-fi
-
-source drivers/parport/Config.in
+  bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+  if [ "$CONFIG_HOTPLUG" = "y" ]; then
+     source drivers/hotplug/Config.in
+     source drivers/pcmcia/Config.in
+  else
+     define_bool CONFIG_PCMCIA n
+  fi
 
+  source drivers/parport/Config.in
 fi # !HP_SIM
 
 endmenu
@@ -123,39 +123,26 @@
 fi
 
 if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+  source drivers/mtd/Config.in
+  source drivers/pnp/Config.in
+  source drivers/block/Config.in
+  source drivers/ieee1394/Config.in
+  source drivers/message/i2o/Config.in
+  source drivers/md/Config.in
+  source drivers/message/fusion/Config.in
 
-source drivers/mtd/Config.in
-source drivers/pnp/Config.in
-source drivers/block/Config.in
-source drivers/ieee1394/Config.in
-source drivers/message/i2o/Config.in
-source drivers/md/Config.in
-source drivers/message/fusion/Config.in
-
-mainmenu_option next_comment
-comment 'ATA/ATAPI/MFM/RLL support'
+  mainmenu_option next_comment
+  comment 'ATA/ATAPI/MFM/RLL support'
 
-tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
+  tristate 'ATA/ATAPI/MFM/RLL support' CONFIG_IDE
 
-if [ "$CONFIG_IDE" != "n" ]; then
-  source drivers/ide/Config.in
-else
-  define_bool CONFIG_BLK_DEV_HD n
-fi
-endmenu
-
-else # ! HP_SIM
-mainmenu_option next_comment
-comment 'Block devices'
-tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
-
-tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
-   int '  Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
+  if [ "$CONFIG_IDE" != "n" ]; then
+    source drivers/ide/Config.in
+  else
+    define_bool CONFIG_BLK_DEV_HD n
+  fi
+  endmenu
 fi
-endmenu
-fi # !HP_SIM
 
 mainmenu_option next_comment
 comment 'SCSI support'
@@ -168,79 +155,82 @@
 endmenu
 
 if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+  if [ "$CONFIG_NET" = "y" ]; then
+    mainmenu_option next_comment
+    comment 'Network device support'
+
+    bool 'Network device support' CONFIG_NETDEVICES
+    if [ "$CONFIG_NETDEVICES" = "y" ]; then
+      source drivers/net/Config.in
+    fi
+    endmenu
+  fi
+  source net/ax25/Config.in
+  source drivers/isdn/Config.in
 
-if [ "$CONFIG_NET" = "y" ]; then
   mainmenu_option next_comment
-  comment 'Network device support'
+  comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
-  bool 'Network device support' CONFIG_NETDEVICES
-  if [ "$CONFIG_NETDEVICES" = "y" ]; then
-    source drivers/net/Config.in
+  bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
+  if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+    source drivers/cdrom/Config.in
   fi
   endmenu
-fi
-
-source net/ax25/Config.in
 
-source drivers/isdn/Config.in
+  #
+  # input before char - char/joystick depends on it. As does USB.
+  #
+  source drivers/input/Config.in
+  source drivers/char/Config.in
 
-mainmenu_option next_comment
-comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
+  #source drivers/misc/Config.in
 
-bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
-if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-  source drivers/cdrom/Config.in
-fi
-endmenu
+  source drivers/media/Config.in
+else # HP_SIM
 
-fi # !HP_SIM
-
-#
-# input before char - char/joystick depends on it. As does USB.
-#
-source drivers/input/Config.in
-source drivers/char/Config.in
-
-#source drivers/misc/Config.in
-
-source drivers/media/Config.in
-
-source fs/Config.in
-
-if [ "$CONFIG_VT" = "y" ]; then
   mainmenu_option next_comment
-  comment 'Console drivers'
-  bool 'VGA text console' CONFIG_VGA_CONSOLE
-  source drivers/video/Config.in
-  if [ "$CONFIG_FB" = "y" ]; then
-    define_bool CONFIG_PCI_CONSOLE y
+  comment 'Block devices'
+  tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
+  dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
+
+  tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
+  if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
+    int '  Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
   fi
   endmenu
-fi
+fi # HP_SIM
 
-if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
-
-mainmenu_option next_comment
-comment 'Sound'
-
-tristate 'Sound card support' CONFIG_SOUND
-if [ "$CONFIG_SOUND" != "n" ]; then
-  source sound/Config.in
-fi
-endmenu
+source fs/Config.in
 
-source drivers/usb/Config.in
+if [ "$CONFIG_IA64_HP_SIM" = "n" ]; then
+  if [ "$CONFIG_VT" = "y" ]; then
+    mainmenu_option next_comment
+    comment 'Console drivers'
+    bool 'VGA text console' CONFIG_VGA_CONSOLE
+    source drivers/video/Config.in
+    if [ "$CONFIG_FB" = "y" ]; then
+      define_bool CONFIG_PCI_CONSOLE y
+    fi
+    endmenu
+  fi
 
-source lib/Config.in
+  mainmenu_option next_comment
+  comment 'Sound'
 
-source net/bluetooth/Config.in
+  tristate 'Sound card support' CONFIG_SOUND
+  if [ "$CONFIG_SOUND" != "n" ]; then
+    source sound/Config.in
+  fi
+  endmenu
 
+  source drivers/usb/Config.in
+  source lib/Config.in
+  source net/bluetooth/Config.in
 fi # !HP_SIM
 
 if [ "$CONFIG_IA64_HP_SIM" != "n" -o "$CONFIG_IA64_GENERIC" != "n" ]; then
-  source arch/ia64/hp/Config.in
+  source arch/ia64/hp/sim/Config.in
 fi
-
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
diff -Nru a/arch/ia64/hp/Config.in b/arch/ia64/hp/Config.in
--- a/arch/ia64/hp/Config.in	Thu Aug  1 01:08:12 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,9 +0,0 @@
-mainmenu_option next_comment
-comment 'HP Simulator drivers'
-
-bool 'Simulated Ethernet ' CONFIG_HP_SIMETH
-bool 'Simulated serial driver support' CONFIG_HP_SIMSERIAL
-if [ "$CONFIG_SCSI" != "n" ]; then
-  bool 'Simulated SCSI disk' CONFIG_HP_SIMSCSI
-fi
-endmenu
diff -Nru a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
--- a/arch/ia64/hp/common/sba_iommu.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/hp/common/sba_iommu.c	Thu Aug  1 01:08:12 2002
@@ -2,6 +2,7 @@
 **  IA64 System Bus Adapter (SBA) I/O MMU manager
 **
 **	(c) Copyright 2002 Alex Williamson
+**	(c) Copyright 2002 Grant Grundler
 **	(c) Copyright 2002 Hewlett-Packard Company
 **
 **	Portions (c) 2000 Grant Grundler (from parisc I/O MMU code)
@@ -110,7 +111,7 @@
 */
 #define DELAYED_RESOURCE_CNT	16
 
-#define DEFAULT_DMA_HINT_REG	0
+#define DEFAULT_DMA_HINT_REG(d)	0
 
 #define ZX1_FUNC_ID_VALUE    ((PCI_DEVICE_ID_HP_ZX1_SBA << 16) | PCI_VENDOR_ID_HP)
 #define ZX1_MC_ID    ((PCI_DEVICE_ID_HP_ZX1_MC << 16) | PCI_VENDOR_ID_HP)
@@ -216,9 +217,10 @@
 static int reserve_sba_gart = 1;
 static struct pci_dev sac_only_dev;
 
-#define sba_sg_iova(sg) (sg->address)
+#define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset)
 #define sba_sg_len(sg) (sg->length)
-#define sba_sg_buffer(sg) (sg->orig_address)
+#define sba_sg_iova(sg) (sg->dma_address)
+#define sba_sg_iova_len(sg) (sg->dma_length)
 
 /* REVISIT - fix me for multiple SBAs/IOCs */
 #define GET_IOC(dev) (sba_list->ioc)
@@ -232,7 +234,7 @@
 ** rather than the HW. I/O MMU allocation alogorithms can be
 ** faster with smaller size is (to some degree).
 */
-#define DMA_CHUNK_SIZE  (BITS_PER_LONG*PAGE_SIZE)
+#define DMA_CHUNK_SIZE  (BITS_PER_LONG*IOVP_SIZE)
 
 /* Looks nice and keeps the compiler happy */
 #define SBA_DEV(d) ((struct sba_device *) (d))
@@ -255,7 +257,7 @@
  * sba_dump_tlb - debugging only - print IOMMU operating parameters
  * @hpa: base address of the IOMMU
  *
- * Print the size/location of the IO MMU PDIR.
+ * Print the size/location of the IO MMU Pdir.
  */
 static void
 sba_dump_tlb(char *hpa)
@@ -273,12 +275,12 @@
 #ifdef ASSERT_PDIR_SANITY
 
 /**
- * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry
+ * sba_dump_pdir_entry - debugging only - print one IOMMU Pdir entry
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @msg: text to print ont the output line.
  * @pide: pdir index.
  *
- * Print one entry of the IO MMU PDIR in human readable form.
+ * Print one entry of the IO MMU Pdir in human readable form.
  */
 static void
 sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
@@ -360,25 +362,25 @@
  * print the SG list so we can verify it's correct by hand.
  */
 static void
-sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
+sba_dump_sg(struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
 	while (nents-- > 0) {
-		printk(" %d : %08lx/%05x %p\n",
+		printk(" %d : DMA %08lx/%05x CPU %p\n",
 				nents,
 				(unsigned long) sba_sg_iova(startsg),
-				sba_sg_len(startsg),
-				sba_sg_buffer(startsg));
+				sba_sg_iova_len(startsg),
+				sba_sg_address(startsg));
 		startsg++;
 	}
 }
 static void
-sba_check_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
+sba_check_sg(struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
 	struct scatterlist *the_sg = startsg;
 	int the_nents = nents;
 
 	while (the_nents-- > 0) {
-		if (sba_sg_buffer(the_sg) == 0x0UL)
+		if (sba_sg_address(the_sg) == 0x0UL)
 			sba_dump_sg(NULL, startsg, nents);
 		the_sg++;
 	}
@@ -404,7 +406,6 @@
 #define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir)))
 #define SBA_IOVP(ioc,iova) (((iova) & ioc->hint_mask_pdir) & ~(ioc->ibase))
 
-/* FIXME : review these macros to verify correctness and usage */
 #define PDIR_INDEX(iovp)   ((iovp)>>IOVP_SHIFT)
 
 #define RESMAP_MASK(n)    ~(~0UL << (n))
@@ -412,7 +413,7 @@
 
 
 /**
- * sba_search_bitmap - find free space in IO PDIR resource bitmap
+ * sba_search_bitmap - find free space in IO Pdir resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @bits_wanted: number of entries we need.
  *
@@ -449,7 +450,7 @@
 		** We need the alignment to invalidate I/O TLB using
 		** SBA HW features in the unmap path.
 		*/
-		unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT);
+		unsigned long o = 1 << get_order(bits_wanted << IOVP_SHIFT);
 		uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
 		unsigned long mask;
 
@@ -495,7 +496,7 @@
 
 
 /**
- * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap
+ * sba_alloc_range - find free bits and mark them in IO Pdir resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @size: number of bytes to create a mapping for
  *
@@ -557,7 +558,7 @@
 
 
 /**
- * sba_free_range - unmark bits in IO PDIR resource bitmap
+ * sba_free_range - unmark bits in IO Pdir resource bitmap
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @iova: IO virtual address which was previously allocated.
  * @size: number of bytes to create a mapping for
@@ -604,14 +605,14 @@
 
 
 /**
- * sba_io_pdir_entry - fill in one IO PDIR entry
- * @pdir_ptr:  pointer to IO PDIR entry
- * @vba: Virtual CPU address of buffer to map
+ * sba_io_pdir_entry - fill in one IO Pdir entry
+ * @pdir_ptr:  pointer to IO Pdir entry
+ * @phys_page: phys CPU address of page to map
  *
  * SBA Mapping Routine
  *
- * Given a virtual address (vba, arg1) sba_io_pdir_entry()
- * loads the I/O PDIR entry pointed to by pdir_ptr (arg0).
+ * Given a physical address (phys_page, arg1) sba_io_pdir_entry()
+ * loads the I/O Pdir entry pointed to by pdir_ptr (arg0).
  * Each IO Pdir entry consists of 8 bytes as shown below
  * (LSB == bit 0):
  *
@@ -623,20 +624,12 @@
  *  V  == Valid Bit
  *  U  == Unused
  * PPN == Physical Page Number
- *
- * The physical address fields are filled with the results of virt_to_phys()
- * on the vba.
  */
 
-#if 1
-#define sba_io_pdir_entry(pdir_ptr, vba) *pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x80000000000000FFULL)
-#else
-void SBA_INLINE
-sba_io_pdir_entry(u64 *pdir_ptr, unsigned long vba)
-{
-	*pdir_ptr = ((vba & ~0xE000000000000FFFULL) | 0x80000000000000FFULL);
-}
-#endif
+#define SBA_VALID_MASK	0x80000000000000FFULL
+#define sba_io_pdir_entry(pdir_ptr, phys_page) *pdir_ptr = (phys_page | SBA_VALID_MASK)
+#define sba_io_page(pdir_ptr) (*pdir_ptr & ~SBA_VALID_MASK)
+
 
 #ifdef ENABLE_MARK_CLEAN
 /**
@@ -660,12 +653,12 @@
 #endif
 
 /**
- * sba_mark_invalid - invalidate one or more IO PDIR entries
+ * sba_mark_invalid - invalidate one or more IO Pdir entries
  * @ioc: IO MMU structure which owns the pdir we are interested in.
  * @iova:  IO Virtual Address mapped earlier
  * @byte_cnt:  number of bytes this mapping covers.
  *
- * Marking the IO PDIR entry(ies) as Invalid and invalidate
+ * Marking the IO Pdir entry(ies) as Invalid and invalidate
  * corresponding IO TLB entry. The PCOM (Purge Command Register)
  * is to purge stale entries in the IO TLB when unmapping entries.
  *
@@ -700,14 +693,14 @@
 		iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
 
 		/*
-		** clear I/O PDIR entry "valid" bit
+		** clear I/O Pdir entry "valid" bit
 		** Do NOT clear the rest - save it for debugging.
 		** We should only clear bits that have previously
 		** been enabled.
 		*/
-		ioc->pdir_base[off] &= ~(0x80000000000000FFULL);
+		ioc->pdir_base[off] &= ~SBA_VALID_MASK;
 	} else {
-		u32 t = get_order(byte_cnt) + PAGE_SHIFT;
+		u32 t = get_order(byte_cnt) + IOVP_SHIFT;
 
 		iovp |= t;
 		ASSERT(t <= 31);   /* 2GB! Max value of "size" field */
@@ -716,7 +709,7 @@
 			/* verify this pdir entry is enabled */
 			ASSERT(ioc->pdir_base[off]  >> 63);
 			/* clear I/O Pdir entry "valid" bit first */
-			ioc->pdir_base[off] &= ~(0x80000000000000FFULL);
+			ioc->pdir_base[off] &= ~SBA_VALID_MASK;
 			off++;
 			byte_cnt -= IOVP_SIZE;
 		} while (byte_cnt > 0);
@@ -744,7 +737,7 @@
 	u64 *pdir_start;
 	int pide;
 #ifdef ALLOW_IOV_BYPASS
-	unsigned long pci_addr = virt_to_phys(addr);
+	unsigned long phys_addr = virt_to_phys(addr);
 #endif
 
 	ioc = GET_IOC(dev);
@@ -754,7 +747,7 @@
 	/*
  	** Check if the PCI device can DMA to ptr... if so, just return ptr
  	*/
-	if ((pci_addr & ~dev->dma_mask) == 0) {
+	if ((phys_addr & ~dev->dma_mask) == 0) {
 		/*
  		** Device is bit capable of DMA'ing to the buffer...
 		** just return the PCI address of ptr
@@ -765,8 +758,8 @@
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
 		DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n",
-		           dev->dma_mask, pci_addr);
-		return pci_addr;
+		           dev->dma_mask, phys_addr);
+		return phys_addr;
 	}
 #endif
 
@@ -799,7 +792,8 @@
 
 	while (size > 0) {
 		ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
-		sba_io_pdir_entry(pdir_start, (unsigned long) addr);
+
+		sba_io_pdir_entry(pdir_start, virt_to_phys(addr));
 
 		DBG_RUN("     pdir 0x%p %lx\n", pdir_start, *pdir_start);
 
@@ -812,7 +806,7 @@
 	sba_check_pdir(ioc,"Check after sba_map_single()");
 #endif
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
-	return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG);
+	return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG(direction));
 }
 
 /**
@@ -866,6 +860,29 @@
 	size += offset;
 	size = ROUNDUP(size, IOVP_SIZE);
 
+#ifdef ENABLE_MARK_CLEAN
+	/*
+	** Don't need to hold the spinlock while telling VM pages are "clean".
+	** The pages are "busy" in the resource map until we mark them free.
+	** But tell VM pages are clean *before* releasing the resource
+	** in order to avoid race conditions.
+	*/
+	if (direction == PCI_DMA_FROMDEVICE) {
+		u32 iovp = (u32) SBA_IOVP(ioc,iova);
+		unsigned int pide = PDIR_INDEX(iovp);
+		u64 *pdirp = &(ioc->pdir_base[pide]);
+		size_t byte_cnt = size;
+		void *addr;
+
+		do {
+			addr = phys_to_virt(sba_io_page(pdirp));
+			mark_clean(addr, min(byte_cnt, IOVP_SIZE));
+			pdirp++;
+			byte_cnt -= IOVP_SIZE;
+		} while (byte_cnt > 0);
+	}
+#endif
+
 	spin_lock_irqsave(&ioc->res_lock, flags);
 #ifdef CONFIG_PROC_FS
 	ioc->usingle_calls++;
@@ -891,40 +908,7 @@
 	sba_free_range(ioc, iova, size);
 	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 #endif /* DELAYED_RESOURCE_CNT == 0 */
-#ifdef ENABLE_MARK_CLEAN
-	if (direction == PCI_DMA_FROMDEVICE) {
-		u32 iovp = (u32) SBA_IOVP(ioc,iova);
-		int off = PDIR_INDEX(iovp);
-		void *addr;
-
-		if (size <= IOVP_SIZE) {
-			addr = phys_to_virt(ioc->pdir_base[off] &
-					    ~0xE000000000000FFFULL);
-			mark_clean(addr, size);
-		} else {
-			size_t byte_cnt = size;
-
-			do {
-				addr = phys_to_virt(ioc->pdir_base[off] &
-				                    ~0xE000000000000FFFULL);
-				mark_clean(addr, min(byte_cnt, IOVP_SIZE));
-				off++;
-				byte_cnt -= IOVP_SIZE;
-
-			   } while (byte_cnt > 0);
-		}
-	}
-#endif
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
-
-	/* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
-	** For Astro based systems this isn't a big deal WRT performance.
-	** As long as 2.4 kernels copyin/copyout data from/to userspace,
-	** we don't need the syncdma. The issue here is I/O MMU cachelines
-	** are *not* coherent in all cases.  May be hwrev dependent.
-	** Need to investigate more.
-	asm volatile("syncdma");	
-	*/
 }
 
 
@@ -980,242 +964,109 @@
 }
 
 
-/*
-** Since 0 is a valid pdir_base index value, can't use that
-** to determine if a value is valid or not. Use a flag to indicate
-** the SG list entry contains a valid pdir index.
-*/
-#define PIDE_FLAG 0x1UL
-
 #ifdef DEBUG_LARGE_SG_ENTRIES
 int dump_run_sg = 0;
 #endif
 
-
-/**
- * sba_fill_pdir - write allocated SG entries into IO PDIR
- * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @startsg:  list of IOVA/size pairs
- * @nents: number of entries in startsg list
- *
- * Take preprocessed SG list and write corresponding entries
- * in the IO PDIR.
- */
-
-static SBA_INLINE int
-sba_fill_pdir(
-	struct ioc *ioc,
-	struct scatterlist *startsg,
-	int nents)
-{
-	struct scatterlist *dma_sg = startsg;	/* pointer to current DMA */
-	int n_mappings = 0;
-	u64 *pdirp = 0;
-	unsigned long dma_offset = 0;
-
-	dma_sg--;
-	while (nents-- > 0) {
-		int     cnt = sba_sg_len(startsg);
-		sba_sg_len(startsg) = 0;
-
-#ifdef DEBUG_LARGE_SG_ENTRIES
-		if (dump_run_sg)
-			printk(" %2d : %08lx/%05x %p\n",
-				nents,
-				(unsigned long) sba_sg_iova(startsg), cnt,
-				sba_sg_buffer(startsg)
-		);
-#else
-		DBG_RUN_SG(" %d : %08lx/%05x %p\n",
-				nents,
-				(unsigned long) sba_sg_iova(startsg), cnt,
-				sba_sg_buffer(startsg)
-		);
-#endif
-		/*
-		** Look for the start of a new DMA stream
-		*/
-		if ((u64)sba_sg_iova(startsg) & PIDE_FLAG) {
-			u32 pide = (u64)sba_sg_iova(startsg) & ~PIDE_FLAG;
-			dma_offset = (unsigned long) pide & ~IOVP_MASK;
-			sba_sg_iova(startsg) = 0;
-			dma_sg++;
-			sba_sg_iova(dma_sg) = (char *)(pide | ioc->ibase);
-			pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]);
-			n_mappings++;
-		}
-
-		/*
-		** Look for a VCONTIG chunk
-		*/
-		if (cnt) {
-			unsigned long vaddr = (unsigned long) sba_sg_buffer(startsg);
-			ASSERT(pdirp);
-
-			/* Since multiple Vcontig blocks could make up
-			** one DMA stream, *add* cnt to dma_len.
-			*/
-			sba_sg_len(dma_sg) += cnt;
-			cnt += dma_offset;
-			dma_offset=0;	/* only want offset on first chunk */
-			cnt = ROUNDUP(cnt, IOVP_SIZE);
-#ifdef CONFIG_PROC_FS
-			ioc->msg_pages += cnt >> IOVP_SHIFT;
-#endif
-			do {
-				sba_io_pdir_entry(pdirp, vaddr);
-				vaddr += IOVP_SIZE;
-				cnt -= IOVP_SIZE;
-				pdirp++;
-			} while (cnt > 0);
-		}
-		startsg++;
-	}
-#ifdef DEBUG_LARGE_SG_ENTRIES
-	dump_run_sg = 0;
-#endif
-	return(n_mappings);
-}
-
-
-/*
-** Two address ranges are DMA contiguous *iff* "end of prev" and
-** "start of next" are both on a page boundry.
-**
-** (shift left is a quick trick to mask off upper bits)
-*/
-#define DMA_CONTIG(__X, __Y) \
-	(((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
+#define SG_ENT_VIRT_PAGE(sg) page_address((sg)->page)
+#define SG_ENT_PHYS_PAGE(SG) virt_to_phys(SG_ENT_VIRT_PAGE(SG))
 
 
 /**
  * sba_coalesce_chunks - preprocess the SG list
  * @ioc: IO MMU structure which owns the pdir we are interested in.
- * @startsg:  list of IOVA/size pairs
+ * @startsg:  input=SG list	output=DMA addr/len pairs filled in
  * @nents: number of entries in startsg list
+ * @direction: R/W or both.
  *
- * First pass is to walk the SG list and determine where the breaks are
- * in the DMA stream. Allocates PDIR entries but does not fill them.
- * Returns the number of DMA chunks.
- *
- * Doing the fill seperate from the coalescing/allocation keeps the
- * code simpler. Future enhancement could make one pass through
- * the sglist do both.
+ * Walk the SG list and determine where the breaks are in the DMA stream.
+ * Allocate IO Pdir resources and fill them in separate loop.
+ * Returns the number of DMA streams used for output IOVA list.
+ * Note each DMA stream can consume multiple IO Pdir entries.
+ *
+ * Code is written assuming some coalescing is possible.
  */
 static SBA_INLINE int
-sba_coalesce_chunks( struct ioc *ioc,
-	struct scatterlist *startsg,
-	int nents)
-{
-	struct scatterlist *vcontig_sg;    /* VCONTIG chunk head */
-	unsigned long vcontig_len;         /* len of VCONTIG chunk */
-	unsigned long vcontig_end;
-	struct scatterlist *dma_sg;        /* next DMA stream head */
-	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+sba_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg,
+	int nents, int direction)
+{
+	struct scatterlist *dma_sg = startsg;	/* return array */
 	int n_mappings = 0;
 
-	while (nents > 0) {
-		unsigned long vaddr = (unsigned long) (startsg->address); 
+	ASSERT(nents > 1);
+
+	do {
+		unsigned int dma_cnt = 1; /* number of pages in DMA stream */
+		unsigned int pide;	/* index into IO Pdir array */
+		u64 *pdirp;		/* pointer into IO Pdir array */
+		unsigned long dma_offset, dma_len; /* cumulative DMA stream */
 
 		/*
 		** Prepare for first/next DMA stream
 		*/
-		dma_sg = vcontig_sg = startsg;
-		dma_len = vcontig_len = vcontig_end = sba_sg_len(startsg);
-		vcontig_end +=  vaddr;
-		dma_offset = vaddr & ~IOVP_MASK;
-
-		/* PARANOID: clear entries */
-		sba_sg_buffer(startsg) = sba_sg_iova(startsg);
-		sba_sg_iova(startsg) = 0;
-		sba_sg_len(startsg) = 0;
+		dma_len = sba_sg_len(startsg);
+		dma_offset = sba_sg_address(startsg);
+		startsg++;
+		nents--;
 
 		/*
-		** This loop terminates one iteration "early" since
-		** it's always looking one "ahead".
+		** We want to know how many entries can be coalesced
+		** before trying to allocate IO Pdir space.
+		** IOVAs can then be allocated "naturally" aligned
+		** to take advantage of the block IO TLB flush.
 		*/
-		while (--nents > 0) {
-			unsigned long vaddr;	/* tmp */
-
-			startsg++;
+		while (nents) {
+			unsigned int end_offset = dma_offset + dma_len;
 
-			/* catch brokenness in SCSI layer */
-			ASSERT(startsg->length <= DMA_CHUNK_SIZE);
+			/* prev entry must end on a page boundary */
+			if (end_offset & IOVP_MASK)
+				break;
 
-			/*
-			** First make sure current dma stream won't
-			** exceed DMA_CHUNK_SIZE if we coalesce the
-			** next entry.
-			*/
-			if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) > DMA_CHUNK_SIZE)
+			/* next entry start on a page boundary? */
+			if (startsg->offset)
 				break;
 
 			/*
-			** Then look for virtually contiguous blocks.
-			**
-			** append the next transaction?
+			** make sure current dma stream won't exceed
+			** DMA_CHUNK_SIZE if coalescing entries.
 			*/
-			vaddr = (unsigned long) sba_sg_iova(startsg);
-			if  (vcontig_end == vaddr)
-			{
-				vcontig_len += sba_sg_len(startsg);
-				vcontig_end += sba_sg_len(startsg);
-				dma_len     += sba_sg_len(startsg);
-				sba_sg_buffer(startsg) = (char *)vaddr;
-				sba_sg_iova(startsg) = 0;
-				sba_sg_len(startsg) = 0;
-				continue;
-			}
+			if (((end_offset + startsg->length + ~IOVP_MASK)
+								& IOVP_MASK)
+					> DMA_CHUNK_SIZE)
+				break;
 
-#ifdef DEBUG_LARGE_SG_ENTRIES
-			dump_run_sg = (vcontig_len > IOVP_SIZE);
-#endif
+			dma_len += sba_sg_len(startsg);
+			startsg++;
+			nents--;
+			dma_cnt++;
+		}
 
-			/*
-			** Not virtually contigous.
-			** Terminate prev chunk.
-			** Start a new chunk.
-			**
-			** Once we start a new VCONTIG chunk, dma_offset
-			** can't change. And we need the offset from the first
-			** chunk - not the last one. Ergo Successive chunks
-			** must start on page boundaries and dove tail
-			** with it's predecessor.
-			*/
-			sba_sg_len(vcontig_sg) = vcontig_len;
+		ASSERT(dma_len <= DMA_CHUNK_SIZE);
 
-			vcontig_sg = startsg;
-			vcontig_len = sba_sg_len(startsg);
+		/* allocate IO Pdir resource.
+		** returns index into (u64) IO Pdir array.
+		** IOVA is formed from this.
+		*/
+		pide = sba_alloc_range(ioc, dma_cnt << IOVP_SHIFT);
+		pdirp = &(ioc->pdir_base[pide]);
 
-			/*
-			** 3) do the entries end/start on page boundaries?
-			**    Don't update vcontig_end until we've checked.
-			*/
-			if (DMA_CONTIG(vcontig_end, vaddr))
-			{
-				vcontig_end = vcontig_len + vaddr;
-				dma_len += vcontig_len;
-				sba_sg_buffer(startsg) = (char *)vaddr;
-				sba_sg_iova(startsg) = 0;
-				continue;
-			} else {
-				break;
-			}
+		/* fill_pdir: write stream into IO Pdir */
+		while (dma_cnt--) {
+			sba_io_pdir_entry(pdirp, SG_ENT_PHYS_PAGE(startsg));
+			startsg++;
+			pdirp++;
 		}
 
-		/*
-		** End of DMA Stream
-		** Terminate last VCONTIG block.
-		** Allocate space for DMA stream.
-		*/
-		sba_sg_len(vcontig_sg) = vcontig_len;
-		dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK;
-		ASSERT(dma_len <= DMA_CHUNK_SIZE);
-		sba_sg_iova(dma_sg) = (char *) (PIDE_FLAG 
-			| (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT)
-			| dma_offset);
+		/* "output" IOVA */
+		sba_sg_iova(dma_sg) = SBA_IOVA(ioc,
+					((dma_addr_t) pide << IOVP_SHIFT),
+					dma_offset,
+					DEFAULT_DMA_HINT_REG(direction));
+		sba_sg_iova_len(dma_sg) = dma_len;
+
+		dma_sg++;
 		n_mappings++;
-	}
+	} while (nents);
 
 	return n_mappings;
 }
@@ -1223,7 +1074,7 @@
 
 /**
  * sba_map_sg - map Scatter/Gather list
- * @dev: instance of PCI owned by the driver that's asking.
+ * @dev: instance of PCI device owned by the driver that's asking.
  * @sglist:  array of buffer/length pairs
  * @nents:  number of entries in list
  * @direction:  R/W or both.
@@ -1234,42 +1085,46 @@
 		int direction)
 {
 	struct ioc *ioc;
-	int coalesced, filled = 0;
+	int filled = 0;
 	unsigned long flags;
 #ifdef ALLOW_IOV_BYPASS
 	struct scatterlist *sg;
 #endif
 
-	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
+	DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n", __FUNCTION__, nents,
+		sba_sg_address(sglist), sba_sg_len(sglist));
+
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
 
 #ifdef ALLOW_IOV_BYPASS
 	if (dev->dma_mask >= ioc->dma_mask) {
-		for (sg = sglist ; filled < nents ; filled++, sg++){
-			sba_sg_buffer(sg) = sba_sg_iova(sg);
-			sba_sg_iova(sg) = (char *)virt_to_phys(sba_sg_buffer(sg));
+		for (sg = sglist ; filled < nents ; filled++, sg++) {
+			sba_sg_iova(sg) = virt_to_phys(sba_sg_address(sg));
+			sba_sg_iova_len(sg) = sba_sg_len(sg);
 		}
 #ifdef CONFIG_PROC_FS
 		spin_lock_irqsave(&ioc->res_lock, flags);
 		ioc->msg_bypass++;
 		spin_unlock_irqrestore(&ioc->res_lock, flags);
 #endif
+		DBG_RUN_SG("%s() DONE %d mappings bypassed\n", __FUNCTION__, filled);
 		return filled;
 	}
 #endif
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
-		sba_sg_buffer(sglist) = sba_sg_iova(sglist);
 		sba_sg_iova(sglist) = (char *)sba_map_single(dev,
-						sba_sg_buffer(sglist),
+						sba_sg_iova(sglist),
 						sba_sg_len(sglist), direction);
+		sba_sg_iova_len(sglist) = sba_sg_len(sglist);
 #ifdef CONFIG_PROC_FS
 		/*
 		** Should probably do some stats counting, but trying to
 		** be precise quickly starts wasting CPU time.
 		*/
 #endif
+		DBG_RUN_SG("%s() DONE 1 mapping\n", __FUNCTION__);
 		return 1;
 	}
 
@@ -1286,26 +1141,11 @@
 #ifdef CONFIG_PROC_FS
 	ioc->msg_calls++;
 #endif
-
-	/*
-	** First coalesce the chunks and allocate I/O pdir space
-	**
-	** If this is one DMA stream, we can properly map using the
-	** correct virtual address associated with each DMA page.
-	** w/o this association, we wouldn't have coherent DMA!
-	** Access to the virtual address is what forces a two pass algorithm.
-	*/
-	coalesced = sba_coalesce_chunks(ioc, sglist, nents);
  
 	/*
-	** Program the I/O Pdir
-	**
-	** map the virtual addresses to the I/O Pdir
-	** o dma_address will contain the pdir index
-	** o dma_len will contain the number of bytes to map 
-	** o address contains the virtual address.
+	** coalesce and program the I/O Pdir
 	*/
-	filled = sba_fill_pdir(ioc, sglist, nents);
+	filled = sba_coalesce_chunks(ioc, sglist, nents, direction);
 
 #ifdef ASSERT_PDIR_SANITY
 	if (sba_check_pdir(ioc,"Check after sba_map_sg()"))
@@ -1317,7 +1157,6 @@
 
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 
-	ASSERT(coalesced == filled);
 	DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
 
 	return filled;
@@ -1341,8 +1180,8 @@
 	unsigned long flags;
 #endif
 
-	DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
-		__FUNCTION__, nents, sba_sg_buffer(sglist), sglist->length);
+	DBG_RUN_SG("%s() START %d entries, 0x%p,0x%x\n",
+		__FUNCTION__, nents, sba_sg_address(sglist), sba_sg_len(sglist));
 
 	ioc = GET_IOC(dev);
 	ASSERT(ioc);
@@ -1360,7 +1199,7 @@
 	while (sba_sg_len(sglist) && nents--) {
 
 		sba_unmap_single(dev, (dma_addr_t)sba_sg_iova(sglist),
-		                 sba_sg_len(sglist), direction);
+		                 sba_sg_iova_len(sglist), direction);
 #ifdef CONFIG_PROC_FS
 		/*
 		** This leaves inconsistent data in the stats, but we can't
@@ -1368,7 +1207,7 @@
 		** were coalesced to a single entry.  The stats are fun,
 		** but speed is more important.
 		*/
-		ioc->usg_pages += (((u64)sba_sg_iova(sglist) & ~IOVP_MASK) + sba_sg_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT;
+		ioc->usg_pages += (((u64)sba_sg_iova(sglist) & ~IOVP_MASK) + sba_sg_len(sglist) + IOVP_SIZE - 1) >> IOVP_SHIFT;
 #endif
 		++sglist;
 	}
@@ -1429,12 +1268,12 @@
 		__FUNCTION__, ioc->ioc_hpa, iova_space_size>>20,
 		iov_order + PAGE_SHIFT, ioc->pdir_size);
 
-	/* FIXME : DMA HINTs not used */
+	/* XXX DMA HINTs not used */
 	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
 	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
 
-	ioc->pdir_base =
-	pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
+	ioc->pdir_base = pdir_base =
+		(void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
 	if (NULL == pdir_base)
 	{
 		panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
@@ -1452,20 +1291,8 @@
 
 	/* build IMASK for IOC and Elroy */
 	iova_space_mask =  0xffffffff;
-	iova_space_mask <<= (iov_order + PAGE_SHIFT);
+	iova_space_mask <<= (iov_order + IOVP_SHIFT);
 
-#ifdef CONFIG_IA64_HP_PROTO
-	/*
-	** REVISIT - this is a kludge, but we won't be supporting anything but
-	** zx1 2.0 or greater for real.  When fw is in shape, ibase will
-	** be preprogrammed w/ the IOVA hole base and imask will give us
-	** the size.
-	*/
-	if ((sba_dev->hw_rev & 0xFF) < 0x20) {
-		DBG_INIT("%s() Found SBA rev < 2.0, setting IOVA base to 0.  This device will not be supported in the future.\n", __FUNCTION__);
-		ioc->ibase = 0x0;
-	} else
-#endif
 	ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & 0xFFFFFFFEUL;
 
 	ioc->imask = iova_space_mask;	/* save it */
@@ -1474,7 +1301,7 @@
 		__FUNCTION__, ioc->ibase, ioc->imask);
 
 	/*
-	** FIXME: Hint registers are programmed with default hint
+	** XXX DMA HINT registers are programmed with default hint
 	** values during boot, so hints should be sane even if we
 	** can't reprogram them the way drivers want.
 	*/
@@ -1487,8 +1314,8 @@
 	*/
 	ioc->imask |= 0xFFFFFFFF00000000UL;
 
-	/* Set I/O PDIR Page size to system page size */
-	switch (PAGE_SHIFT) {
+	/* Set I/O Pdir page size to system page size */
+	switch (IOVP_SHIFT) {
 		case 12: /* 4K */
 			tcnfg = 0;
 			break;
@@ -1636,7 +1463,7 @@
 				res_word = (int)(index / BITS_PER_LONG);
 				mask =  0x1UL << (index - (res_word * BITS_PER_LONG));
 				res_ptr[res_word] |= mask;
-				sba_dev->ioc[i].pdir_base[PDIR_INDEX(reserved_iov)] = (0x80000000000000FFULL | reserved_iov);
+				sba_dev->ioc[i].pdir_base[PDIR_INDEX(reserved_iov)] = (SBA_VALID_MASK | reserved_iov);
 
 			}
 		}
diff -Nru a/arch/ia64/hp/sim/Config.in b/arch/ia64/hp/sim/Config.in
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/hp/sim/Config.in	Thu Aug  1 01:08:12 2002
@@ -0,0 +1,9 @@
+mainmenu_option next_comment
+comment 'HP Simulator drivers'
+
+bool 'Simulated Ethernet ' CONFIG_HP_SIMETH
+bool 'Simulated serial driver support' CONFIG_HP_SIMSERIAL
+if [ "$CONFIG_SCSI" != "n" ]; then
+  bool 'Simulated SCSI disk' CONFIG_HP_SIMSCSI
+fi
+endmenu
diff -Nru a/arch/ia64/hp/sim/hpsim_console.c b/arch/ia64/hp/sim/hpsim_console.c
--- a/arch/ia64/hp/sim/hpsim_console.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/hp/sim/hpsim_console.c	Thu Aug  1 01:08:12 2002
@@ -30,12 +30,12 @@
 static kdev_t simcons_console_device (struct console *);
 
 struct console hpsim_cons = {
-	name:		"simcons",
-	write:		simcons_write,
-	device:		simcons_console_device,
-	setup:		simcons_init,
-	flags:		CON_PRINTBUFFER,
-	index:		-1,
+	.name =		"simcons",
+	.write =	simcons_write,
+	.device =	simcons_console_device,
+	.setup =	simcons_init,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
 };
 
 static int
diff -Nru a/arch/ia64/hp/sim/hpsim_irq.c b/arch/ia64/hp/sim/hpsim_irq.c
--- a/arch/ia64/hp/sim/hpsim_irq.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/hp/sim/hpsim_irq.c	Thu Aug  1 01:08:13 2002
@@ -22,14 +22,14 @@
 }
 
 static struct hw_interrupt_type irq_type_hp_sim = {
-	typename:	"hpsim",
-	startup:	hpsim_irq_startup,
-	shutdown:	hpsim_irq_noop,
-	enable:		hpsim_irq_noop,
-	disable:	hpsim_irq_noop,
-	ack:		hpsim_irq_noop,
-	end:		hpsim_irq_noop,
-	set_affinity:	(void (*)(unsigned int, unsigned long)) hpsim_irq_noop,
+	.typename =	"hpsim",
+	.startup =	hpsim_irq_startup,
+	.shutdown =	hpsim_irq_noop,
+	.enable =	hpsim_irq_noop,
+	.disable =	hpsim_irq_noop,
+	.ack =		hpsim_irq_noop,
+	.end =		hpsim_irq_noop,
+	.set_affinity =	(void (*)(unsigned int, unsigned long)) hpsim_irq_noop,
 };
 
 void __init
diff -Nru a/arch/ia64/hp/sim/hpsim_setup.c b/arch/ia64/hp/sim/hpsim_setup.c
--- a/arch/ia64/hp/sim/hpsim_setup.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/hp/sim/hpsim_setup.c	Thu Aug  1 01:08:13 2002
@@ -1,18 +1,19 @@
 /*
  * Platform dependent support for HP simulator.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  * Copyright (C) 1999 Vijay Chander <vijay@engr.sgi.com>
  */
+#include <linux/console.h>
 #include <linux/init.h>
+#include <linux/kdev_t.h>
 #include <linux/kernel.h>
+#include <linux/major.h>
 #include <linux/param.h>
+#include <linux/root_dev.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#include <linux/kdev_t.h>
-#include <linux/console.h>
-#include <linux/root_dev.h>
 
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -55,5 +56,5 @@
 {
 	ROOT_DEV = Root_SDA1;		/* default to first SCSI drive */
 
-	register_console (&hpsim_cons);
+	register_console(&hpsim_cons);
 }
diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c
--- a/arch/ia64/hp/sim/simscsi.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/hp/sim/simscsi.c	Thu Aug  1 01:08:13 2002
@@ -62,7 +62,9 @@
 
 extern long ia64_ssc (long arg0, long arg1, long arg2, long arg3, int nr);
 
-static int desc[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+static int desc[16] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
 
 static struct queue_entry {
 	Scsi_Cmnd *sc;
@@ -148,9 +150,9 @@
 {
 	int size = disk->capacity;
 
-	ip[0] = 64;
-	ip[1] = 32;
-	ip[2] = size >> 11;
+	ip[0] = 64;		/* heads */
+	ip[1] = 32;		/* sectors */
+	ip[2] = size >> 11;	/* cylinders */
 	return 0;
 }
 
@@ -229,6 +231,29 @@
 		simscsi_readwrite(sc, mode, offset, sc->cmnd[4]*512);
 }
 
+static size_t
+simscsi_get_disk_size (int fd)
+{
+	struct disk_stat stat;
+	size_t bit, sectors = 0;
+	struct disk_req req;
+	char buf[512];
+
+	/*
+	 * This is a bit kludgey: the simulator doesn't provide a direct way of determining
+	 * the disk size, so we do a binary search, assuming a maximum disk size of 4GB.
+	 */
+	for (bit = (4UL << 30)/512; bit != 0; bit >>= 1) {
+		req.addr = __pa(&buf);
+		req.len = sizeof(buf);
+		ia64_ssc(fd, 1, __pa(&req), ((sectors | bit) - 1)*512, SSC_READ);
+		stat.fd = fd;
+		ia64_ssc(__pa(&stat), 0, 0, 0, SSC_WAIT_COMPLETION);
+		if (stat.count == sizeof(buf))
+			sectors |= bit;
+	}
+	return sectors - 1;	/* return last valid sector number */
+}
 
 static void
 simscsi_readwrite10 (Scsi_Cmnd *sc, int mode)
@@ -247,6 +272,7 @@
 simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *))
 {
 	char fname[MAX_ROOT_LEN+16];
+	size_t disk_size;
 	char *buf;
 #if DEBUG_SIMSCSI
 	register long sp asm ("sp");
@@ -258,15 +284,15 @@
 
 	sc->result = DID_BAD_TARGET << 16;
 	sc->scsi_done = done;
-	if (sc->target <= 7 && sc->lun == 0) {
+	if (sc->target <= 15 && sc->lun == 0) {
 		switch (sc->cmnd[0]) {
 		      case INQUIRY:
 			if (sc->request_bufflen < 35) {
 				break;
 			}
 			sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target);
-			desc[sc->target] = ia64_ssc (__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
-						     0, 0, SSC_OPEN);
+			desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS,
+						    0, 0, SSC_OPEN);
 			if (desc[sc->target] < 0) {
 				/* disk doesn't exist... */
 				break;
@@ -319,11 +345,13 @@
 			}
 			buf = sc->request_buffer;
 
+			disk_size = simscsi_get_disk_size(desc[sc->target]);
+
 			/* pretend to be a 1GB disk (partition table contains real stuff): */
-			buf[0] = 0x00;
-			buf[1] = 0x1f;
-			buf[2] = 0xff;
-			buf[3] = 0xff;
+			buf[0] = (disk_size >> 24) & 0xff;
+			buf[1] = (disk_size >> 16) & 0xff;
+			buf[2] = (disk_size >>  8) & 0xff;
+			buf[3] = (disk_size >>  0) & 0xff;
 			/* set block size of 512 bytes: */
 			buf[4] = 0;
 			buf[5] = 0;
diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c
--- a/arch/ia64/hp/sim/simserial.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/hp/sim/simserial.c	Thu Aug  1 01:08:13 2002
@@ -13,6 +13,7 @@
  *
  * 02/04/00 D. Mosberger	Merged in serial.c bug fixes in rs_close().
  * 02/25/00 D. Mosberger	Synced up with 2.3.99pre-5 version of serial.c.
+ * 07/30/02 D. Mosberger	Replace sti()/cli() with explicit spinlocks & local irq masking
  */
 
 #include <linux/config.h>
@@ -31,6 +32,7 @@
 #include <linux/serialP.h>
 
 #include <asm/irq.h>
+#include <asm/hw_irq.h>
 #include <asm/uaccess.h>
 
 #ifdef CONFIG_KDB
@@ -61,6 +63,7 @@
 
 static char *serial_name = "SimSerial driver";
 static char *serial_version = "0.6";
+static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This has been extracted from asm/serial.h. We need one eventually but
@@ -232,14 +235,14 @@
 
 	if (!tty || !info->xmit.buf) return;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&serial_lock, flags);
 	if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&serial_lock, flags);
 		return;
 	}
 	info->xmit.buf[info->xmit.head] = ch;
 	info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&serial_lock, flags);
 }
 
 static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done)
@@ -247,7 +250,7 @@
 	int count;
 	unsigned long flags;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&serial_lock, flags);
 
 	if (info->x_char) {
 		char c = info->x_char;
@@ -290,7 +293,7 @@
 		info->xmit.tail += count;
 	}
 out:
-	restore_flags(flags);
+	spin_unlock_irqrestore(&serial_lock, flags);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
@@ -314,7 +317,6 @@
 
 	if (!tty || !info->xmit.buf || !tmp_buf) return 0;
 
-	save_flags(flags);
 	if (from_user) {
 		down(&tmp_buf_sem);
 		while (1) {
@@ -331,21 +333,26 @@
 					ret = -EFAULT;
 				break;
 			}
-			cli();
-			c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-			if (c1 < c)
-				c = c1;
-			memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
-			info->xmit.head = ((info->xmit.head + c) &
-					   (SERIAL_XMIT_SIZE-1));
-			restore_flags(flags);
+
+			spin_lock_irqsave(&serial_lock, flags);
+			{
+				c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail,
+						       SERIAL_XMIT_SIZE);
+				if (c1 < c)
+					c = c1;
+				memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
+				info->xmit.head = ((info->xmit.head + c) &
+						   (SERIAL_XMIT_SIZE-1));
+			}
+			spin_unlock_irqrestore(&serial_lock, flags);
+
 			buf += c;
 			count -= c;
 			ret += c;
 		}
 		up(&tmp_buf_sem);
 	} else {
-		cli();
+		spin_lock_irqsave(&serial_lock, flags);
 		while (1) {
 			c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
 			if (count < c)
@@ -360,7 +367,7 @@
 			count -= c;
 			ret += c;
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&serial_lock, flags);
 	}
 	/*
 	 * Hey, we transmit directly from here in our case
@@ -391,9 +398,9 @@
 	struct async_struct *info = (struct async_struct *)tty->driver_data;
 	unsigned long flags;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&serial_lock, flags);
 	info->xmit.head = info->xmit.tail = 0;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&serial_lock, flags);
 
 	wake_up_interruptible(&tty->write_wait);
 
@@ -566,44 +573,45 @@
 	       state->irq);
 #endif
 
-	save_flags(flags); cli(); /* Disable interrupts */
-
-	/*
-	 * First unlink the serial port from the IRQ chain...
-	 */
-	if (info->next_port)
-		info->next_port->prev_port = info->prev_port;
-	if (info->prev_port)
-		info->prev_port->next_port = info->next_port;
-	else
-		IRQ_ports[state->irq] = info->next_port;
+	spin_lock_irqsave(&serial_lock, flags);
+	{
+		/*
+		 * First unlink the serial port from the IRQ chain...
+		 */
+		if (info->next_port)
+			info->next_port->prev_port = info->prev_port;
+		if (info->prev_port)
+			info->prev_port->next_port = info->next_port;
+		else
+			IRQ_ports[state->irq] = info->next_port;
 
-	/*
-	 * Free the IRQ, if necessary
-	 */
-	if (state->irq && (!IRQ_ports[state->irq] ||
-			  !IRQ_ports[state->irq]->next_port)) {
-		if (IRQ_ports[state->irq]) {
-			free_irq(state->irq, NULL);
-			retval = request_irq(state->irq, rs_interrupt_single,
-					     IRQ_T(info), "serial", NULL);
-
-			if (retval)
-				printk("serial shutdown: request_irq: error %d"
-				       "  Couldn't reacquire IRQ.\n", retval);
-		} else
-			free_irq(state->irq, NULL);
-	}
+		/*
+		 * Free the IRQ, if necessary
+		 */
+		if (state->irq && (!IRQ_ports[state->irq] ||
+				   !IRQ_ports[state->irq]->next_port)) {
+			if (IRQ_ports[state->irq]) {
+				free_irq(state->irq, NULL);
+				retval = request_irq(state->irq, rs_interrupt_single,
+						     IRQ_T(info), "serial", NULL);
+
+				if (retval)
+					printk("serial shutdown: request_irq: error %d"
+					       "  Couldn't reacquire IRQ.\n", retval);
+			} else
+				free_irq(state->irq, NULL);
+		}
 
-	if (info->xmit.buf) {
-		free_page((unsigned long) info->xmit.buf);
-		info->xmit.buf = 0;
-	}
+		if (info->xmit.buf) {
+			free_page((unsigned long) info->xmit.buf);
+			info->xmit.buf = 0;
+		}
 
-	if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
+		if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
 
-	info->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
+		info->flags &= ~ASYNC_INITIALIZED;
+	}
+	spin_unlock_irqrestore(&serial_lock, flags);
 }
 
 /*
@@ -626,14 +634,13 @@
 
 	state = info->state;
 
-	save_flags(flags); cli();
-
+	spin_lock_irqsave(&serial_lock, flags);
 	if (tty_hung_up_p(filp)) {
 #ifdef SIMSERIAL_DEBUG
 		printk("rs_close: hung_up\n");
 #endif
 		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&serial_lock, flags);
 		return;
 	}
 #ifdef SIMSERIAL_DEBUG
@@ -658,11 +665,11 @@
 	}
 	if (state->count) {
 		MOD_DEC_USE_COUNT;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&serial_lock, flags);
 		return;
 	}
 	info->flags |= ASYNC_CLOSING;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&serial_lock, flags);
 
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify
@@ -770,7 +777,7 @@
 	if (!page)
 		return -ENOMEM;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&serial_lock, flags);
 
 	if (info->flags & ASYNC_INITIALIZED) {
 		free_page(page);
@@ -851,11 +858,11 @@
 	}
 
 	info->flags |= ASYNC_INITIALIZED;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&serial_lock, flags);
 	return 0;
 
 errout:
-	restore_flags(flags);
+	spin_unlock_irqrestore(&serial_lock, flags);
 	return retval;
 }
 
diff -Nru a/arch/ia64/hp/zx1/hpzx1_machvec.c b/arch/ia64/hp/zx1/hpzx1_machvec.c
--- a/arch/ia64/hp/zx1/hpzx1_machvec.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/hp/zx1/hpzx1_machvec.c	Thu Aug  1 01:08:13 2002
@@ -1,4 +1,2 @@
 #define MACHVEC_PLATFORM_NAME	hpzx1
 #include <asm/machvec_init.h>
-#define MACHVEC_PLATFORM_NAME	hpzx1
-#include <asm/machvec_init.h>
diff -Nru a/arch/ia64/hp/zx1/hpzx1_misc.c b/arch/ia64/hp/zx1/hpzx1_misc.c
--- a/arch/ia64/hp/zx1/hpzx1_misc.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/hp/zx1/hpzx1_misc.c	Thu Aug  1 01:08:13 2002
@@ -27,6 +27,7 @@
 #include "../drivers/acpi/include/acstruct.h"
 #include "../drivers/acpi/include/acnamesp.h"
 #include "../drivers/acpi/include/acutils.h"
+#include "../drivers/acpi/acpi_bus.h"
 
 #define PFX "hpzx1: "
 
@@ -109,7 +110,7 @@
 	\
 	switch (where) { \
 	case PCI_BASE_ADDRESS_0: \
-		if (value == ~0) \
+		if (value == (u##bits) ~0) \
 			fake_dev->sizing = 1; \
 		break; \
 	default: \
@@ -177,7 +178,7 @@
 	 * Drivers should ioremap what they need, but we have to do
 	 * it here, too, so PCI config accesses work.
 	 */
-	dev->mapped_csrs = ioremap(dev->csr_base, dev->csr_size);
+	dev->mapped_csrs = (unsigned long) ioremap(dev->csr_base, dev->csr_size);
 
 	return dev;
 }
@@ -303,7 +304,7 @@
 	if ((dev = hpzx1_fake_pci_dev(csr_base, busnum, csr_length)))
 		printk(KERN_INFO PFX "%s LBA at 0x%lx, _BBN 0x%02x; "
 			"pci dev %02x:%02x.%d\n",
-			name, csr_base, busnum, dev->bus,
+			name, csr_base, (unsigned int) busnum, dev->bus,
 			PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
 
 	return AE_OK;
diff -Nru a/arch/ia64/ia32/binfmt_elf32.c b/arch/ia64/ia32/binfmt_elf32.c
--- a/arch/ia64/ia32/binfmt_elf32.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/ia32/binfmt_elf32.c	Thu Aug  1 01:08:13 2002
@@ -67,7 +67,7 @@
 }
 
 static struct vm_operations_struct ia32_shared_page_vm_ops = {
-	nopage:	ia32_install_shared_page
+	.nopage =ia32_install_shared_page
 };
 
 void
diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
--- a/arch/ia64/ia32/ia32_ioctl.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/ia32/ia32_ioctl.c	Thu Aug  1 01:08:13 2002
@@ -30,6 +30,8 @@
 #include <asm/ia32.h>
 
 #include <../drivers/char/drm/drm.h>
+#include <../drivers/char/drm/mga_drm.h>
+#include <../drivers/char/drm/i810_drm.h>
 
 
 #define IOCTL_NR(a)	((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
--- a/arch/ia64/kernel/acpi.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/acpi.c	Thu Aug  1 01:08:13 2002
@@ -56,16 +56,19 @@
 void (*pm_idle) (void);
 void (*pm_power_off) (void);
 
+unsigned char acpi_kbd_controller_present = 1;
+
 const char *
 acpi_get_sysname (void)
 {
 #ifdef CONFIG_IA64_GENERIC
-	unsigned long rsdp_phys = 0;
+	unsigned long rsdp_phys;
 	struct acpi20_table_rsdp *rsdp;
 	struct acpi_table_xsdt *xsdt;
 	struct acpi_table_header *hdr;
 
-	if ((0 != acpi_find_rsdp(&rsdp_phys)) || !rsdp_phys) {
+	rsdp_phys = acpi_find_rsdp();
+	if (!rsdp_phys) {
 		printk("ACPI 2.0 RSDP not found, default to \"dig\"\n");
 		return "dig";
 	}
@@ -99,6 +102,8 @@
 	return "sn2";
 # elif defined (CONFIG_IA64_DIG)
 	return "dig";
+# elif defined (CONFIG_IA64_HP_ZX1)
+	return "hpzx1";
 # else
 #	error Unknown platform.  Fix acpi.c.
 # endif
@@ -130,9 +135,7 @@
 	if (!buf->pointer)
 		return -ENOMEM;
 
-	result = acpi_get_current_resources(obj, buf);
-
-	return result;
+	return acpi_get_current_resources(obj, buf);
 }
 
 acpi_resource *
@@ -175,6 +178,8 @@
 /* Array to record platform interrupt vectors for generic interrupt routing. */
 int platform_irq_list[ACPI_MAX_PLATFORM_IRQS] = { [0 ... ACPI_MAX_PLATFORM_IRQS - 1] = -1 };
 
+enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC;
+
 /*
  * Interrupt routing API for device drivers.  Provides interrupt vector for
  * a generic platform event.  Currently only CPEI is implemented.
@@ -189,10 +194,14 @@
 		vector = platform_irq_list[int_type];
 	} else
 		printk("acpi_request_vector(): invalid interrupt type\n");
-
 	return vector;
 }
 
+char *
+__acpi_map_table (unsigned long phys_addr, unsigned long size)
+{
+	return __va(phys_addr);
+}
 
 /* --------------------------------------------------------------------------
                             Boot-time Table Parsing
@@ -206,7 +215,7 @@
 static int __init
 acpi_parse_lapic_addr_ovr (acpi_table_entry_header *header)
 {
-	struct acpi_table_lapic_addr_ovr *lapic = NULL;
+	struct acpi_table_lapic_addr_ovr *lapic;
 
 	lapic = (struct acpi_table_lapic_addr_ovr *) header;
 	if (!lapic)
@@ -218,7 +227,6 @@
 		iounmap((void *) ipi_base_addr);
 		ipi_base_addr = (unsigned long) ioremap(lapic->address, 0);
 	}
-
 	return 0;
 }
 
@@ -226,7 +234,7 @@
 static int __init
 acpi_parse_lsapic (acpi_table_entry_header *header)
 {
-	struct acpi_table_lsapic *lsapic = NULL;
+	struct acpi_table_lsapic *lsapic;
 
 	lsapic = (struct acpi_table_lsapic *) header;
 	if (!lsapic)
@@ -262,7 +270,7 @@
 static int __init
 acpi_parse_lapic_nmi (acpi_table_entry_header *header)
 {
-	struct acpi_table_lapic_nmi *lacpi_nmi = NULL;
+	struct acpi_table_lapic_nmi *lacpi_nmi;
 
 	lacpi_nmi = (struct acpi_table_lapic_nmi*) header;
 	if (!lacpi_nmi)
@@ -271,7 +279,6 @@
 	acpi_table_print_madt_entry(header);
 
 	/* TBD: Support lapic_nmi entries */
-
 	return 0;
 }
 
@@ -279,11 +286,11 @@
 static int __init
 acpi_find_iosapic (int global_vector, u32 *irq_base, char **iosapic_address)
 {
-	struct acpi_table_iosapic *iosapic = NULL;
-	int ver = 0;
-	int max_pin = 0;
-	char *p = 0;
-	char *end = 0;
+	struct acpi_table_iosapic *iosapic;
+	int ver;
+	int max_pin;
+	char *p;
+	char *end;
 
 	if (!irq_base || !iosapic_address)
 		return -ENODEV;
@@ -338,10 +345,10 @@
 static int __init
 acpi_parse_plat_int_src (acpi_table_entry_header *header)
 {
-	struct acpi_table_plat_int_src *plintsrc = NULL;
-	int vector = 0;
-	u32 irq_base = 0;
-	char *iosapic_address = NULL;
+	struct acpi_table_plat_int_src *plintsrc;
+	int vector;
+	u32 irq_base;
+	char *iosapic_address;
 
 	plintsrc = (struct acpi_table_plat_int_src *) header;
 	if (!plintsrc)
@@ -354,7 +361,7 @@
 		return -ENODEV;
 	}
 
-	if (0 != acpi_find_iosapic(plintsrc->global_irq, &irq_base, &iosapic_address)) {
+	if (acpi_find_iosapic(plintsrc->global_irq, &irq_base, &iosapic_address)) {
 		printk(KERN_WARNING PREFIX "IOSAPIC not found\n");
 		return -ENODEV;
 	}
@@ -363,15 +370,15 @@
 	 * Get vector assignment for this IRQ, set attributes, and program the
 	 * IOSAPIC routing table.
 	 */
-	vector = iosapic_register_platform_irq (plintsrc->type,
-						plintsrc->global_irq,
-						plintsrc->iosapic_vector,
-						plintsrc->eid,
-						plintsrc->id,
-						(plintsrc->flags.polarity == 1) ? 1 : 0,
-						(plintsrc->flags.trigger == 1) ? 1 : 0,
-						irq_base,
-						iosapic_address);
+	vector = iosapic_register_platform_irq(plintsrc->type,
+					       plintsrc->global_irq,
+					       plintsrc->iosapic_vector,
+					       plintsrc->eid,
+					       plintsrc->id,
+					       (plintsrc->flags.polarity == 1) ? 1 : 0,
+					       (plintsrc->flags.trigger == 1) ? 1 : 0,
+					       irq_base,
+					       iosapic_address);
 
 	platform_irq_list[plintsrc->type] = vector;
 	return 0;
@@ -381,7 +388,7 @@
 static int __init
 acpi_parse_int_src_ovr (acpi_table_entry_header *header)
 {
-	struct acpi_table_int_src_ovr *p = NULL;
+	struct acpi_table_int_src_ovr *p;
 
 	p = (struct acpi_table_int_src_ovr *) header;
 	if (!p)
@@ -394,9 +401,8 @@
 		return 0;
 
 	iosapic_register_legacy_irq(p->bus_irq, p->global_irq,
-		(p->flags.polarity == 1) ? 1 : 0,
-		(p->flags.trigger == 1) ? 1 : 0);
-
+				    (p->flags.polarity == 1) ? 1 : 0,
+				    (p->flags.trigger == 1) ? 1 : 0);
 	return 0;
 }
 
@@ -404,7 +410,7 @@
 static int __init
 acpi_parse_nmi_src (acpi_table_entry_header *header)
 {
-	struct acpi_table_nmi_src *nmi_src = NULL;
+	struct acpi_table_nmi_src *nmi_src;
 
 	nmi_src = (struct acpi_table_nmi_src*) header;
 	if (!nmi_src)
@@ -413,7 +419,6 @@
 	acpi_table_print_madt_entry(header);
 
 	/* TBD: Support nimsrc entries */
-
 	return 0;
 }
 
@@ -425,38 +430,47 @@
 		return -EINVAL;
 
 	acpi_madt = (struct acpi_table_madt *) __va(phys_addr);
-	if (!acpi_madt) {
-		printk(KERN_WARNING PREFIX "Unable to map MADT\n");
-		return -ENODEV;
-	}
 
 	/* Get base address of IPI Message Block */
 
 	if (acpi_madt->lapic_address)
-		ipi_base_addr = (unsigned long)
-			ioremap(acpi_madt->lapic_address, 0);
+		ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0);
 
 	printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr);
-
 	return 0;
 }
 
-
-int __init
-acpi_find_rsdp (unsigned long *rsdp_phys)
+static int __init
+acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
 {
-	if (!rsdp_phys)
+	struct acpi_table_header *fadt_header;
+	fadt_descriptor_rev2 *fadt;
+
+	if (!phys_addr || !size)
 		return -EINVAL;
 
-	if (efi.acpi20) {
-		(*rsdp_phys) = __pa(efi.acpi20);
-		return 0;
-	}
-	else if (efi.acpi) {
-		printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
-	}
+	fadt_header = (struct acpi_table_header *) __va(phys_addr);
+	if (fadt_header->revision != 3)
+		return -ENODEV;		/* Only deal with ACPI 2.0 FADT */
 
-	return -ENODEV;
+	fadt = (fadt_descriptor_rev2 *) fadt_header;
+
+	if (!(fadt->iapc_boot_arch & BAF_8042_KEYBOARD_CONTROLLER))
+		acpi_kbd_controller_present = 0;
+
+	return 0;
+}
+
+unsigned long __init
+acpi_find_rsdp (void)
+{
+	unsigned long rsdp_phys = 0;
+
+	if (efi.acpi20)
+		rsdp_phys = __pa(efi.acpi20);
+	else if (efi.acpi)
+		printk(KERN_WARNING PREFIX "v1.0/r0.71 tables no longer supported\n");
+	return rsdp_phys;
 }
 
 
@@ -467,8 +481,8 @@
 static int __init
 acpi_parse_spcr (unsigned long phys_addr, unsigned long size)
 {
-	acpi_ser_t *spcr = NULL;
-	unsigned long global_int = 0;
+	acpi_ser_t *spcr;
+	unsigned long global_int;
 
 	if (!phys_addr || !size)
 		return -EINVAL;
@@ -486,11 +500,6 @@
 	 */
 
 	spcr = (acpi_ser_t *) __va(phys_addr);
-	if (!spcr) {
-		printk(KERN_WARNING PREFIX "Unable to map SPCR\n");
-		return -ENODEV;
-	}
-
 	setup_serial_acpi(spcr);
 
 	if (spcr->length < sizeof(acpi_ser_t))
@@ -500,38 +509,37 @@
 	if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) &&
 	    (spcr->int_type == ACPI_SERIAL_INT_SAPIC))
 	{
-		u32 irq_base = 0;
-		char *iosapic_address = NULL;
-		int vector = 0;
+		u32 irq_base;
+		char *iosapic_address;
+		int vector;
 
 		/* We have a UART in memory space with an SAPIC interrupt */
 
-		global_int = (  (spcr->global_int[3] << 24) |
-				(spcr->global_int[2] << 16) |
-				(spcr->global_int[1] << 8)  |
-				(spcr->global_int[0])  );
+		global_int = ((spcr->global_int[3] << 24) |
+			      (spcr->global_int[2] << 16) |
+			      (spcr->global_int[1] << 8)  |
+			      (spcr->global_int[0])  );
 
 		/* Which iosapic does this IRQ belong to? */
 
-		if (0 == acpi_find_iosapic(global_int, &irq_base, &iosapic_address)) {
-			vector = iosapic_register_irq (global_int, 1, 1,
-						       irq_base, iosapic_address);
-		}
+		if (!acpi_find_iosapic(global_int, &irq_base, &iosapic_address))
+			vector = iosapic_register_irq(global_int, 1, 1,
+						      irq_base, iosapic_address);
 	}
 	return 0;
 }
 
-#endif /*CONFIG_SERIAL_ACPI*/
+#endif /* CONFIG_SERIAL_ACPI */
 
 
 int __init
 acpi_boot_init (char *cmdline)
 {
-	int result = 0;
+	int result;
 
 	/* Initialize the ACPI boot-time table parser */
 	result = acpi_table_init(cmdline);
-	if (0 != result)
+	if (result)
 		return result;
 
 	/*
@@ -542,57 +550,42 @@
 	 * information -- the successor to MPS tables.
 	 */
 
-	result = acpi_table_parse(ACPI_APIC, acpi_parse_madt);
-	if (1 > result)
-		return result;
+	if (acpi_table_parse(ACPI_APIC, acpi_parse_madt) < 1) {
+		printk(KERN_ERR PREFIX "Can't find MADT\n");
+		goto skip_madt;
+	}
 
 	/* Local APIC */
 
-	result = acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr);
-	if (0 > result) {
+	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_ADDR_OVR, acpi_parse_lapic_addr_ovr) < 0)
 		printk(KERN_ERR PREFIX "Error parsing LAPIC address override entry\n");
-		return result;
-	}
 
-	result = acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic);
-	if (1 > result) {
-		printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries!\n");
-		return -ENODEV;
-	}
+	if (acpi_table_parse_madt(ACPI_MADT_LSAPIC, acpi_parse_lsapic) < 1)
+		printk(KERN_ERR PREFIX "Error parsing MADT - no LAPIC entries\n");
 
-	result = acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi);
-	if (0 > result) {
+	if (acpi_table_parse_madt(ACPI_MADT_LAPIC_NMI, acpi_parse_lapic_nmi) < 0)
 		printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
-		return result;
-	}
 
 	/* I/O APIC */
 
-	result = acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic);
-	if (1 > result) {
-		printk(KERN_ERR PREFIX "Error parsing MADT - no IOAPIC entries!\n");
-		return ((result == 0) ? -ENODEV : result);
-	}
+	if (acpi_table_parse_madt(ACPI_MADT_IOSAPIC, acpi_parse_iosapic) < 1)
+		printk(KERN_ERR PREFIX "Error parsing MADT - no IOSAPIC entries\n");
 
 	/* System-Level Interrupt Routing */
 
-	result = acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src);
-	if (0 > result) {
+	if (acpi_table_parse_madt(ACPI_MADT_PLAT_INT_SRC, acpi_parse_plat_int_src) < 0)
 		printk(KERN_ERR PREFIX "Error parsing platform interrupt source entry\n");
-		return result;
-	}
 
-	result = acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr);
-	if (0 > result) {
+	if (acpi_table_parse_madt(ACPI_MADT_INT_SRC_OVR, acpi_parse_int_src_ovr) < 0)
 		printk(KERN_ERR PREFIX "Error parsing interrupt source overrides entry\n");
-		return result;
-	}
 
-	result = acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src);
-	if (0 > result) {
+	if (acpi_table_parse_madt(ACPI_MADT_NMI_SRC, acpi_parse_nmi_src) < 0)
 		printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
-		return result;
-	}
+  skip_madt:
+
+	/* FADT says whether a legacy keyboard controller is present. */
+	if (acpi_table_parse(ACPI_FACP, acpi_parse_fadt) < 1)
+		printk(KERN_ERR PREFIX "Can't find FADT\n");
 
 #ifdef CONFIG_SERIAL_ACPI
 	/*
@@ -602,7 +595,7 @@
 	 *      serial ports, EC, SMBus, etc.
 	 */
 	acpi_table_parse(ACPI_SPCR, acpi_parse_spcr);
-#endif /*CONFIG_SERIAL_ACPI*/
+#endif
 
 #ifdef CONFIG_SMP
 	if (available_cpus == 0) {
@@ -613,7 +606,6 @@
 #endif
 	/* Make boot-up look pretty */
 	printk("%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
-
 	return 0;
 }
 
@@ -625,9 +617,9 @@
 int __init
 acpi_get_prt (struct pci_vector_struct **vectors, int *count)
 {
-	struct pci_vector_struct *vector = NULL;
-	struct list_head *node = NULL;
-	struct acpi_prt_entry *entry = NULL;
+	struct pci_vector_struct *vector;
+	struct list_head *node;
+	struct acpi_prt_entry *entry;
 	int i = 0;
 
 	if (!vectors || !count)
@@ -636,14 +628,14 @@
 	*vectors = NULL;
 	*count = 0;
 
-	if (acpi_prts.count <= 0) {
+	if (acpi_prt.count < 0) {
 		printk(KERN_ERR PREFIX "No PCI IRQ routing entries\n");
 		return -ENODEV;
 	}
 
 	/* Allocate vectors */
 
-	*vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prts.count, GFP_KERNEL);
+	*vectors = kmalloc(sizeof(struct pci_vector_struct) * acpi_prt.count, GFP_KERNEL);
 	if (!(*vectors))
 		return -ENOMEM;
 
@@ -651,15 +643,15 @@
 
 	vector = *vectors;
 
-	list_for_each(node, &acpi_prts.entries) {
+	list_for_each(node, &acpi_prt.entries) {
 		entry = (struct acpi_prt_entry *)node;
 		vector[i].bus    = entry->id.bus;
-		vector[i].pci_id = ((u32) entry->id.dev << 16) | 0xffff;
-		vector[i].pin    = entry->id.pin;
-		vector[i].irq    = entry->source.index;
+		vector[i].pci_id = ((u32) entry->id.device << 16) | 0xffff;
+		vector[i].pin    = entry->pin;
+		vector[i].irq    = entry->link.index;
 		i++;
 	}
-	*count = acpi_prts.count;
+	*count = acpi_prt.count;
 	return 0;
 }
 
@@ -671,8 +663,7 @@
         if (!type)
                 return -EINVAL;
 
-	*type = ACPI_INT_MODEL_IOSAPIC;
-
+	*type = ACPI_IRQ_MODEL_IOSAPIC;
         return 0;
 }
 
diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
--- a/arch/ia64/kernel/efi.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/efi.c	Thu Aug  1 01:08:12 2002
@@ -125,9 +125,79 @@
 	tv->tv_usec = tm.nanosecond / 1000;
 }
 
+static int
+is_available_memory (efi_memory_desc_t *md)
+{
+	if (!(md->attribute & EFI_MEMORY_WB))
+		return 0;
+
+	switch (md->type) {
+	      case EFI_LOADER_CODE:
+	      case EFI_LOADER_DATA:
+	      case EFI_BOOT_SERVICES_CODE:
+	      case EFI_BOOT_SERVICES_DATA:
+	      case EFI_CONVENTIONAL_MEMORY:
+		return 1;
+	}
+	return 0;
+}
+
 /*
- * Walks the EFI memory map and calls CALLBACK once for each EFI
- * memory descriptor that has memory that is available for OS use.
+ * Trim descriptor MD so its starts at address START_ADDR.  If the descriptor covers
+ * memory that is normally available to the kernel, issue a warning that some memory
+ * is being ignored.
+ */
+static void
+trim_bottom (efi_memory_desc_t *md, u64 start_addr)
+{
+	u64 num_skipped_pages;
+
+	if (md->phys_addr >= start_addr || !md->num_pages)
+		return;
+
+	num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
+	if (num_skipped_pages > md->num_pages)
+		num_skipped_pages = md->num_pages;
+
+	if (is_available_memory(md))
+		printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
+		       "at 0x%lx\n", __FUNCTION__,
+		       (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
+		       md->phys_addr, start_addr - IA64_GRANULE_SIZE);
+	/*
+	 * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
+	 * descriptor list to become unsorted.  In such a case, md->num_pages will be
+	 * zero, so the Right Thing will happen.
+	 */
+	md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
+	md->num_pages -= num_skipped_pages;
+}
+
+static void
+trim_top (efi_memory_desc_t *md, u64 end_addr)
+{
+	u64 num_dropped_pages, md_end_addr;
+
+	md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
+
+	if (md_end_addr <= end_addr || !md->num_pages)
+		return;
+
+	num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT;
+	if (num_dropped_pages > md->num_pages)
+		num_dropped_pages = md->num_pages;
+
+	if (is_available_memory(md))
+		printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
+		       "at 0x%lx\n", __FUNCTION__,
+		       (num_dropped_pages << EFI_PAGE_SHIFT) >> 10,
+		       md->phys_addr, end_addr);
+	md->num_pages -= num_dropped_pages;
+}
+
+/*
+ * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
+ * has memory that is available for OS use.
  */
 void
 efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
@@ -137,9 +207,9 @@
 		u64 start;
 		u64 end;
 	} prev, curr;
-	void *efi_map_start, *efi_map_end, *p;
-	efi_memory_desc_t *md;
-	u64 efi_desc_size, start, end;
+	void *efi_map_start, *efi_map_end, *p, *q;
+	efi_memory_desc_t *md, *check_md;
+	u64 efi_desc_size, start, end, granule_addr, first_non_wb_addr = 0;
 
 	efi_map_start = __va(ia64_boot_param->efi_memmap);
 	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
@@ -147,24 +217,56 @@
 
 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
 		md = p;
-		switch (md->type) {
-		      case EFI_LOADER_CODE:
-		      case EFI_LOADER_DATA:
-		      case EFI_BOOT_SERVICES_CODE:
-		      case EFI_BOOT_SERVICES_DATA:
-		      case EFI_CONVENTIONAL_MEMORY:
-			if (!(md->attribute & EFI_MEMORY_WB))
-				continue;
+
+		/* skip over non-WB memory descriptors; that's all we're interested in... */
+		if (!(md->attribute & EFI_MEMORY_WB))
+			continue;
+
+		if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > first_non_wb_addr) {
+			/*
+			 * Search for the next run of contiguous WB memory.  Start search
+			 * at first granule boundary covered by md.
+			 */
+			granule_addr = ((md->phys_addr + IA64_GRANULE_SIZE - 1)
+					& -IA64_GRANULE_SIZE);
+			first_non_wb_addr = granule_addr;
+			for (q = p; q < efi_map_end; q += efi_desc_size) {
+				check_md = q;
+
+				if (check_md->attribute & EFI_MEMORY_WB)
+					trim_bottom(md, granule_addr);
+
+				if (check_md->phys_addr < granule_addr)
+					continue;
+
+				if (!(check_md->attribute & EFI_MEMORY_WB))
+					break;	/* hit a non-WB region; stop search */
+
+				if (check_md->phys_addr != first_non_wb_addr)
+					break;	/* hit a memory hole; stop search */
+
+				first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
+			}
+			/* round it down to the previous granule-boundary: */
+			first_non_wb_addr &= -IA64_GRANULE_SIZE;
+
+			if (!(first_non_wb_addr > granule_addr))
+				continue;	/* couldn't find enough contiguous memory */
+		}
+
+		/* BUG_ON((md->phys_addr >> IA64_GRANULE_SHIFT) < first_non_wb_addr); */
+
+		trim_top(md, first_non_wb_addr);
+
+		if (is_available_memory(md)) {
 			if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
 				if (md->phys_addr > mem_limit)
 					continue;
 				md->num_pages = (mem_limit - md->phys_addr) >> EFI_PAGE_SHIFT;
 			}
-			if (md->num_pages == 0) {
-				printk("efi_memmap_walk: ignoring empty region at 0x%lx",
-				       md->phys_addr);
+
+			if (md->num_pages == 0)
 				continue;
-			}
 
 			curr.start = PAGE_OFFSET + md->phys_addr;
 			curr.end   = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
@@ -187,10 +289,6 @@
 					prev = curr;
 				}
 			}
-			break;
-
-		      default:
-			continue;
 		}
 	}
 	if (prev_valid) {
@@ -268,8 +366,9 @@
 		 */
 		psr = ia64_clear_ic();
 		ia64_itr(0x1, IA64_TR_PALCODE, vaddr & mask,
-			 pte_val(pfn_pte(md->phys_addr >> PAGE_SHIFT, PAGE_KERNEL)), IA64_GRANULE_SHIFT);
-		ia64_set_psr(psr);
+			 pte_val(pfn_pte(md->phys_addr >> PAGE_SHIFT, PAGE_KERNEL)),
+			 IA64_GRANULE_SHIFT);
+		ia64_set_psr(psr);		/* restore psr */
 		ia64_srlz_i();
 	}
 }
@@ -376,7 +475,7 @@
 			md = p;
 			printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
 			       i, md->type, md->attribute, md->phys_addr,
-			       md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1,
+			       md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT),
 			       md->num_pages >> (20 - EFI_PAGE_SHIFT));
 		}
 	}
diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
--- a/arch/ia64/kernel/entry.S	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/entry.S	Thu Aug  1 01:08:12 2002
@@ -175,6 +175,7 @@
 (p6)	srlz.d
 	ld8 sp=[r21]			// load kernel stack pointer of new task
 	mov IA64_KR(CURRENT)=r20	// update "current" application register
+	mov r8=r13			// return pointer to previously running task
 	mov r13=in0			// set "current" pointer
 	;;
 	DO_LOAD_SWITCH_STACK
diff -Nru a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
--- a/arch/ia64/kernel/ia64_ksyms.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/ia64_ksyms.c	Thu Aug  1 01:08:13 2002
@@ -88,12 +88,6 @@
 #include <asm/smplock.h>
 EXPORT_SYMBOL(kernel_flag);
 
-/* #include <asm/system.h> */
-EXPORT_SYMBOL(__global_sti);
-EXPORT_SYMBOL(__global_cli);
-EXPORT_SYMBOL(__global_save_flags);
-EXPORT_SYMBOL(__global_restore_flags);
-
 #else /* !CONFIG_SMP */
 
 EXPORT_SYMBOL(__flush_tlb_all);
diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c
--- a/arch/ia64/kernel/init_task.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/init_task.c	Thu Aug  1 01:08:13 2002
@@ -34,8 +34,8 @@
 	} s;
 	unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)];
 } init_thread_union __attribute__((section(".data.init_task"))) = {{
-	task: INIT_TASK(init_thread_union.s.task),
-	thread_info: INIT_THREAD_INFO(init_thread_union.s.thread_info)
+	.task =		INIT_TASK(init_thread_union.s.task),
+	.thread_info =	INIT_THREAD_INFO(init_thread_union.s.thread_info)
 }};
 
 asm (".global init_task; init_task = init_thread_union");
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/iosapic.c	Thu Aug  1 01:08:13 2002
@@ -88,7 +88,7 @@
 
 static struct iosapic_irq {
 	char *addr;			/* base address of IOSAPIC */
-	unsigned char base_irq;		/* first irq assigned to this IOSAPIC */
+	unsigned int base_irq;		/* first irq assigned to this IOSAPIC */
 	char pin;			/* IOSAPIC pin (-1 => not an IOSAPIC irq) */
 	unsigned char dmode	: 3;	/* delivery mode (see iosapic.h) */
 	unsigned char polarity	: 1;	/* interrupt polarity (see iosapic.h) */
@@ -97,9 +97,9 @@
 
 static struct iosapic {
 	char *addr;			/* base address of IOSAPIC */
-	unsigned char	pcat_compat;	/* 8259 compatibility flag */
-	unsigned char 	base_irq;	/* first irq assigned to this IOSAPIC */
+	unsigned int 	base_irq;	/* first irq assigned to this IOSAPIC */
 	unsigned short 	max_pin;	/* max input pin supported in this IOSAPIC */
+	unsigned char	pcat_compat;	/* 8259 compatibility flag */
 } iosapic_lists[256] __initdata;
 
 static int num_iosapic = 0;
@@ -322,14 +322,14 @@
 #define iosapic_ack_level_irq		nop
 
 struct hw_interrupt_type irq_type_iosapic_level = {
-	typename:	"IO-SAPIC-level",
-	startup:	iosapic_startup_level_irq,
-	shutdown:	iosapic_shutdown_level_irq,
-	enable:		iosapic_enable_level_irq,
-	disable:	iosapic_disable_level_irq,
-	ack:		iosapic_ack_level_irq,
-	end:		iosapic_end_level_irq,
-	set_affinity:	iosapic_set_affinity
+	.typename =	"IO-SAPIC-level",
+	.startup =	iosapic_startup_level_irq,
+	.shutdown =	iosapic_shutdown_level_irq,
+	.enable =	iosapic_enable_level_irq,
+	.disable =	iosapic_disable_level_irq,
+	.ack =		iosapic_ack_level_irq,
+	.end =		iosapic_end_level_irq,
+	.set_affinity =	iosapic_set_affinity
 };
 
 /*
@@ -366,14 +366,14 @@
 #define iosapic_end_edge_irq		nop
 
 struct hw_interrupt_type irq_type_iosapic_edge = {
-	typename:	"IO-SAPIC-edge",
-	startup:	iosapic_startup_edge_irq,
-	shutdown:	iosapic_disable_edge_irq,
-	enable:		iosapic_enable_edge_irq,
-	disable:	iosapic_disable_edge_irq,
-	ack:		iosapic_ack_edge_irq,
-	end:		iosapic_end_edge_irq,
-	set_affinity:	iosapic_set_affinity
+	.typename =	"IO-SAPIC-edge",
+	.startup =	iosapic_startup_edge_irq,
+	.shutdown =	iosapic_disable_edge_irq,
+	.enable =	iosapic_enable_edge_irq,
+	.disable =	iosapic_disable_edge_irq,
+	.ack =		iosapic_ack_edge_irq,
+	.end =		iosapic_end_edge_irq,
+	.set_affinity =	iosapic_set_affinity
 };
 
 unsigned int
@@ -422,6 +422,7 @@
 	irq_desc_t *idesc;
 	struct hw_interrupt_type *irq_type;
 
+	gsi_to_vector(global_vector) = vector;
 	iosapic_irq[vector].pin	= pin;
 	iosapic_irq[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW;
 	iosapic_irq[vector].dmode    = delivery;
@@ -640,7 +641,7 @@
 	unsigned int irq;
 	char *addr;
 
-	if (0 != acpi_get_prt(&pci_irq.route, &pci_irq.num_routes))
+	if (acpi_get_prt(&pci_irq.route, &pci_irq.num_routes))
 		return;
 
 	for (i = 0; i < pci_irq.num_routes; i++) {
@@ -679,11 +680,10 @@
 		       pci_irq.route[i].bus, pci_irq.route[i].pci_id>>16, pci_irq.route[i].pin,
 		       iosapic_irq[vector].base_irq + iosapic_irq[vector].pin, vector);
 #endif
-
 		/*
-		 * Forget not to program the IOSAPIC RTE per ACPI _PRT
+		 * NOTE: The IOSAPIC RTE will be programmed in iosapic_pci_fixup().  It
+		 * needs to be done there to ensure PCI hotplug works right.
 		 */
-		set_rte(vector, (ia64_get_lid() >> 16) & 0xffff);
 	}
 }
 
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/irq.c	Thu Aug  1 01:08:12 2002
@@ -200,277 +200,12 @@
 	return 0;
 }
 
-
-/*
- * Global interrupt locks for SMP. Allow interrupts to come in on any
- * CPU, yet make cli/sti act globally to protect critical regions..
- */
-
-#ifdef CONFIG_SMP
-unsigned int global_irq_holder = NO_PROC_ID;
-unsigned volatile long global_irq_lock; /* pedantic: long for set_bit --RR */
-
-extern void show_stack(unsigned long* esp);
-
-static void show(char * str)
+#if CONFIG_SMP
+inline void synchronize_irq(unsigned int irq)
 {
-	int i;
-	int cpu = smp_processor_id();
-
-	printk("\n%s, CPU %d:\n", str, cpu);
-	printk("irq:  %d [",irqs_running());
-	for(i=0;i < NR_CPUS;i++)
-		printk(" %d",irq_count(i));
-	printk(" ]\nbh:   %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
-	for(i=0;i < NR_CPUS;i++)
-		printk(" %d",bh_count(i));
-
-	printk(" ]\nStack dumps:");
-#if defined(CONFIG_IA64)
-	/*
-	 * We can't unwind the stack of another CPU without access to
-	 * the registers of that CPU.  And sending an IPI when we're
-	 * in a potentially wedged state doesn't sound like a smart
-	 * idea.
-	 */
-#elif defined(CONFIG_X86)
-	for(i=0;i< NR_CPUS;i++) {
-		unsigned long esp;
-		if(i==cpu)
-			continue;
-		printk("\nCPU %d:",i);
-		esp = init_tss[i].esp0;
-		if(esp==NULL) {
-			/* tss->esp0 is set to NULL in cpu_init(),
-			 * it's initialized when the cpu returns to user
-			 * space. -- manfreds
-			 */
-			printk(" <unknown> ");
-			continue;
-		}
-		esp &= ~(THREAD_SIZE-1);
-		esp += sizeof(struct task_struct);
-		show_stack((void*)esp);
-	}
-#else
-	You lose...
-#endif
-	printk("\nCPU %d:",cpu);
-	show_stack(NULL);
-	printk("\n");
+	while (irq_desc(irq)->status & IRQ_INPROGRESS)
+		cpu_relax();
 }
-
-#define MAXCOUNT 100000000
-
-/*
- * I had a lockup scenario where a tight loop doing
- * spin_unlock()/spin_lock() on CPU#1 was racing with
- * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
- * apparently the spin_unlock() information did not make it
- * through to CPU#0 ... nasty, is this by design, do we have to limit
- * 'memory update oscillation frequency' artificially like here?
- *
- * Such 'high frequency update' races can be avoided by careful design, but
- * some of our major constructs like spinlocks use similar techniques,
- * it would be nice to clarify this issue. Set this define to 0 if you
- * want to check whether your system freezes.  I suspect the delay done
- * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
- * i thought that such things are guaranteed by design, since we use
- * the 'LOCK' prefix.
- */
-#define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 0
-
-#if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
-# define SYNC_OTHER_CORES(x) udelay(x+1)
-#else
-/*
- * We have to allow irqs to arrive between local_irq_enable and local_irq_disable
- */
-# ifdef CONFIG_IA64
-#  define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop 0")
-# else
-#  define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
-# endif
-#endif
-
-static inline void wait_on_irq(void)
-{
-	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 (really_local_bh_count() || !spin_is_locked(&global_bh_lock))
-				break;
-
-		/* Duh, we have to loop. Release the lock to avoid deadlocks */
-		smp_mb__before_clear_bit();	/* need barrier before releasing lock... */
-		clear_bit(0,&global_irq_lock);
-
-		for (;;) {
-			if (!--count) {
-				show("wait_on_irq");
-				count = ~0;
-			}
-			local_irq_enable();
-			SYNC_OTHER_CORES(smp_processor_id());
-			local_irq_disable();
-			if (irqs_running())
-				continue;
-			if (global_irq_lock)
-				continue;
-			if (!really_local_bh_count() && 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
- * 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(void)
-{
-	if (test_and_set_bit(0,&global_irq_lock)) {
-		/* do we already hold the lock? */
-		if (smp_processor_id() == global_irq_holder)
-			return;
-		/* Uhhuh.. Somebody else got it. Wait.. */
-		do {
-			do {
-#ifdef CONFIG_X86
-				rep_nop();
-#endif
-			} while (test_bit(0,&global_irq_lock));
-		} while (test_and_set_bit(0,&global_irq_lock));
-	}
-	/*
-	 * We also to make sure that nobody else is running
-	 * in an interrupt context.
-	 */
-	wait_on_irq();
-
-	/*
-	 * Ok, finally..
-	 */
-	global_irq_holder = smp_processor_id();
-}
-
-#define EFLAGS_IF_SHIFT 9
-
-/*
- * 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 int flags;
-
-#ifdef CONFIG_IA64
-	local_save_flags(flags);
-	if (flags & IA64_PSR_I) {
-		local_irq_disable();
-		if (!really_local_irq_count())
-			get_irqlock();
-	}
-#else
-	local_save_flags(flags);
-	if (flags & (1 << EFLAGS_IF_SHIFT)) {
-		local_irq_disable();
-		if (!really_local_irq_count())
-			get_irqlock();
-	}
-#endif
-}
-
-void __global_sti(void)
-{
-	if (!really_local_irq_count())
-		release_irqlock(smp_processor_id());
-	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;
-	int cpu = smp_processor_id();
-
-	local_save_flags(flags);
-#ifdef CONFIG_IA64
-	local_enabled = (flags & IA64_PSR_I) != 0;
-#else
-	local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
-#endif
-	/* default to local */
-	retval = 2 + local_enabled;
-
-	/* check for global flags if we're not in an interrupt */
-	if (!really_local_irq_count()) {
-		if (local_enabled)
-			retval = 1;
-		if (global_irq_holder == cpu)
-			retval = 0;
-	}
-	return retval;
-}
-
-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:
-		printk("global_restore_flags: %08lx (%08lx)\n",
-			flags, (&flags)[-1]);
-	}
-}
-
 #endif
 
 /*
@@ -482,11 +217,7 @@
  */
 int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
-	int status;
-
-	local_irq_enter(irq);
-
-	status = 1;	/* Force the "do bottom halves" bit */
+	int status = 1;	/* Force the "do bottom halves" bit */
 
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
@@ -500,11 +231,16 @@
 		add_interrupt_randomness(irq);
 	local_irq_disable();
 
-	local_irq_exit(irq);
-
 	return status;
 }
 
+/*
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock.
+ */
+
 /**
  *	disable_irq_nosync - disable an irq without waiting
  *	@irq: Interrupt to disable
@@ -546,14 +282,7 @@
 void disable_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-
-#ifdef CONFIG_SMP
-	if (!really_local_irq_count()) {
-		do {
-			barrier();
-		} while (irq_desc(irq)->status & IRQ_INPROGRESS);
-	}
-#endif
+	synchronize_irq(irq);
 }
 
 /**
@@ -616,6 +345,7 @@
 	struct irqaction * action;
 	unsigned int status;
 
+	irq_enter();
 	kstat.irqs[cpu][irq]++;
 
 	if (desc->status & IRQ_PER_CPU) {
@@ -682,6 +412,7 @@
 		desc->handler->end(irq);
 		spin_unlock(&desc->lock);
 	}
+	irq_exit();
 	return 1;
 }
 
@@ -811,7 +542,7 @@
 #ifdef CONFIG_SMP
 			/* Wait to make sure it's not being used on another CPU */
 			while (desc->status & IRQ_INPROGRESS)
-				barrier();
+				synchronize_irq(irq);
 #endif
 			kfree(action);
 			return;
@@ -864,7 +595,7 @@
 
 	/* Wait for longstanding interrupts to trigger. */
 	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-		/* about 20ms delay */ synchronize_irq();
+		/* about 20ms delay */ barrier();
 
 	/*
 	 * enable any unassigned irqs
@@ -887,7 +618,7 @@
 	 * Wait for spurious interrupts to trigger
 	 */
 	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-		/* about 100ms delay */ synchronize_irq();
+		/* about 100ms delay */ barrier();
 
 	/*
 	 * Now filter out any obviously spurious interrupts
diff -Nru a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
--- a/arch/ia64/kernel/irq_ia64.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/irq_ia64.c	Thu Aug  1 01:08:13 2002
@@ -36,6 +36,10 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_PERFMON
+# include <asm/perfmon.h>
+#endif
+
 #define IRQ_DEBUG	0
 
 /* default base addr of IPI table */
@@ -50,6 +54,11 @@
 	0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21
 };
 
+/*
+ * GSI to IA-64 vector translation table.
+ */
+__u8 gsi_to_vector_map[255];
+
 int
 ia64_alloc_irq (void)
 {
@@ -144,9 +153,9 @@
 extern void handle_IPI (int irq, void *dev_id, struct pt_regs *regs);
 
 static struct irqaction ipi_irqaction = {
-	handler:	handle_IPI,
-	flags:		SA_INTERRUPT,
-	name:		"IPI"
+	.handler =	handle_IPI,
+	.flags =	SA_INTERRUPT,
+	.name =		"IPI"
 };
 #endif
 
@@ -172,6 +181,9 @@
 	register_percpu_irq(IA64_SPURIOUS_INT_VECTOR, NULL);
 #ifdef CONFIG_SMP
 	register_percpu_irq(IA64_IPI_VECTOR, &ipi_irqaction);
+#endif
+#ifdef CONFIG_PERFMON
+	perfmon_init_percpu();
 #endif
 	platform_irq_init();
 }
diff -Nru a/arch/ia64/kernel/irq_lsapic.c b/arch/ia64/kernel/irq_lsapic.c
--- a/arch/ia64/kernel/irq_lsapic.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/irq_lsapic.c	Thu Aug  1 01:08:12 2002
@@ -27,12 +27,12 @@
 }
 
 struct hw_interrupt_type irq_type_ia64_lsapic = {
-	typename:	"LSAPIC",
-	startup:	lsapic_noop_startup,
-	shutdown:	lsapic_noop,
-	enable:		lsapic_noop,
-	disable:	lsapic_noop,
-	ack:		lsapic_noop,
-	end:		lsapic_noop,
-	set_affinity:	(void (*)(unsigned int, unsigned long)) lsapic_noop
+	.typename =	"LSAPIC",
+	.startup =	lsapic_noop_startup,
+	.shutdown =	lsapic_noop,
+	.enable =	lsapic_noop,
+	.disable =	lsapic_noop,
+	.ack =		lsapic_noop,
+	.end =		lsapic_noop,
+	.set_affinity =	(void (*)(unsigned int, unsigned long)) lsapic_noop
 };
diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c
--- a/arch/ia64/kernel/machvec.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/machvec.c	Thu Aug  1 01:08:13 2002
@@ -11,13 +11,16 @@
 struct ia64_machine_vector ia64_mv;
 
 /*
- * Most platforms use this routine for mapping page frame addresses
- * into a memory map index.
+ * Most platforms use this routine for mapping page frame addresses into a memory map
+ * index.
+ *
+ * Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if
+ * X is outside the identity mapped kernel space.
  */
 unsigned long
 map_nr_dense (unsigned long addr)
 {
-	return MAP_NR_DENSE(addr);
+	return (addr - PAGE_OFFSET) >> PAGE_SHIFT;
 }
 
 static struct ia64_machine_vector *
diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
--- a/arch/ia64/kernel/mca.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/mca.c	Thu Aug  1 01:08:13 2002
@@ -82,27 +82,27 @@
 extern struct hw_interrupt_type	irq_type_iosapic_level;
 
 static struct irqaction cmci_irqaction = {
-	handler:    ia64_mca_cmc_int_handler,
-	flags:      SA_INTERRUPT,
-	name:       "cmc_hndlr"
+	.handler =	ia64_mca_cmc_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"cmc_hndlr"
 };
 
 static struct irqaction mca_rdzv_irqaction = {
-	handler:    ia64_mca_rendez_int_handler,
-	flags:      SA_INTERRUPT,
-	name:       "mca_rdzv"
+	.handler =	ia64_mca_rendez_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"mca_rdzv"
 };
 
 static struct irqaction mca_wkup_irqaction = {
-	handler:    ia64_mca_wakeup_int_handler,
-	flags:      SA_INTERRUPT,
-	name:       "mca_wkup"
+	.handler =	ia64_mca_wakeup_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"mca_wkup"
 };
 
 static struct irqaction mca_cpe_irqaction = {
-	handler:    ia64_mca_cpe_int_handler,
-	flags:      SA_INTERRUPT,
-	name:       "cpe_hndlr"
+	.handler =	ia64_mca_cpe_int_handler,
+	.flags =	SA_INTERRUPT,
+	.name =		"cpe_hndlr"
 };
 
 /*
@@ -626,9 +626,12 @@
 void
 ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs)
 {
-	int flags, cpu = 0;
+	unsigned long flags;
+	int cpu = 0;
+
 	/* Mask all interrupts */
-	save_and_cli(flags);
+#warning XXX fix me: this used to be: save_and_cli(flags);
+	local_irq_save(flags);
 
 #ifdef CONFIG_SMP
 	cpu = cpu_logical_id(hard_smp_processor_id());
@@ -646,7 +649,7 @@
 	ia64_mca_wakeup_ipi_wait();
 
 	/* Enable all interrupts */
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 
diff -Nru a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
--- a/arch/ia64/kernel/mca_asm.S	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/mca_asm.S	Thu Aug  1 01:08:12 2002
@@ -684,9 +684,9 @@
 	movl	r3=SAL_GET_STATE_INFO;;
 	DATA_VA_TO_PA(r7);;		// convert to physical address
 	ld8	r8=[r7],8;;		// get pdesc function pointer
-	DATA_VA_TO_PA(r8)		// convert to physical address
+	dep	r8=0,r8,61,3;;		// convert SAL VA to PA
 	ld8	r1=[r7];;		// set new (ia64_sal) gp
-	DATA_VA_TO_PA(r1)		// convert to physical address
+	dep	r1=0,r1,61,3;;		// convert SAL VA to PA
 	mov	b6=r8
 
 	alloc	r5=ar.pfs,8,0,8,0;;	// allocate stack frame for SAL call
diff -Nru a/arch/ia64/kernel/pci.c b/arch/ia64/kernel/pci.c
--- a/arch/ia64/kernel/pci.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/pci.c	Thu Aug  1 01:08:13 2002
@@ -165,7 +165,7 @@
  */
 
 struct pci_bus *
-pcibios_scan_root(int seg, int bus)
+pcibios_scan_root(int bus)
 {
 	struct list_head *list = NULL;
 	struct pci_bus *pci_bus = NULL;
@@ -174,12 +174,12 @@
 		pci_bus = pci_bus_b(list);
 		if (pci_bus->number == bus) {
 			/* Already scanned */
-			printk("PCI: Bus (%02x:%02x) already probed\n", seg, bus);
+			printk("PCI: Bus (%02x) already probed\n", bus);
 			return pci_bus;
 		}
 	}
 
-	printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus);
+	printk("PCI: Probing PCI hardware on bus (%02x)\n", bus);
 
 	return pci_scan_bus(bus, pci_root_ops, NULL);
 }
@@ -265,12 +265,37 @@
 int
 pcibios_enable_device (struct pci_dev *dev)
 {
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
 	if (!dev)
 		return -EINVAL;
 
-	/* Not needed, since we enable all devices at startup.  */
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR
+			       "PCI: Device %s not available because of resource collisions\n",
+			       dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
 
 	printk(KERN_INFO "PCI: Found IRQ %d for device %s\n", dev->irq, dev->slot_name);
+
 	return 0;
 }
 
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/perfmon.c	Thu Aug  1 01:08:13 2002
@@ -106,6 +106,12 @@
 
 #define PFM_REG_RETFLAG_SET(flags, val)	do { flags &= ~PFM_REG_RETFL_MASK; flags |= (val); } while(0)
 
+#ifdef CONFIG_SMP
+#define cpu_is_online(i) (cpu_online_map & (1UL << i))
+#else
+#define cpu_is_online(i)        (i==0)
+#endif
+
 /*
  * debugging
  */
@@ -277,8 +283,8 @@
 typedef struct {
 	pfm_pmu_reg_type_t	type;
 	int			pm_pos;
-	int			(*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val);
-	int			(*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val);
+	int			(*read_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
+	int			(*write_check)(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
 	unsigned long		dep_pmd[4];
 	unsigned long		dep_pmc[4];
 } pfm_reg_desc_t;
@@ -396,7 +402,7 @@
 static void pfm_vm_close(struct vm_area_struct * area);
 
 static struct vm_operations_struct pfm_vm_ops={
-	close: pfm_vm_close
+	.close = pfm_vm_close
 };
 
 /*
@@ -610,7 +616,7 @@
 
 	down_write(&task->mm->mmap_sem);
 
-	r = do_munmap(task->mm, ctx->ctx_smpl_vaddr, psb->psb_size);
+	r = do_munmap(task->mm, ctx->ctx_smpl_vaddr, psb->psb_size, 0);
 
 	up_write(&task->mm->mmap_sem);
 	if (r !=0) {
@@ -902,8 +908,8 @@
 		/*
 		 * and it must be a valid CPU
 		 */
-		cpu = ffs(pfx->ctx_cpu_mask);
-		if (!cpu_online(cpu)) {
+		cpu = ffz(~pfx->ctx_cpu_mask);
+		if (cpu_is_online(cpu) == 0) {
 			DBprintk(("CPU%d is not online\n", cpu));
 			return -EINVAL;
 		}
@@ -925,11 +931,12 @@
 			DBprintk(("must have notify_pid when blocking for [%d]\n", task->pid));
 			return -EINVAL;
 		}
-
+#if 0
 		if ((ctx_flags & PFM_FL_NOTIFY_BLOCK) && pfx->ctx_notify_pid == task->pid) {
 			DBprintk(("cannot notify self when blocking for [%d]\n", task->pid));
 			return -EINVAL;
 		}
+#endif
 	}
 	/* probably more to add here */
 
@@ -968,7 +975,7 @@
 	if (ctx_flags & PFM_FL_SYSTEM_WIDE) {
 
 		/* at this point, we know there is at least one bit set */
-		cpu = ffs(tmp.ctx_cpu_mask) - 1;
+		cpu = ffz(~tmp.ctx_cpu_mask);
 
 		DBprintk(("requesting CPU%d currently on CPU%d\n",cpu, smp_processor_id()));
 
@@ -1280,7 +1287,7 @@
 		/*
 		 * execute write checker, if any
 		 */
-		if (PMC_WR_FUNC(cnum)) ret = PMC_WR_FUNC(cnum)(task, cnum, &tmp.reg_value);
+		if (PMC_WR_FUNC(cnum)) ret = PMC_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
 abort_mission:
 		if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL;
 
@@ -1371,7 +1378,7 @@
 		/*
 		 * execute write checker, if any
 		 */
-		if (PMD_WR_FUNC(cnum)) ret = PMD_WR_FUNC(cnum)(task, cnum, &tmp.reg_value);
+		if (PMD_WR_FUNC(cnum)) ret = PMD_WR_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
 abort_mission:
 		if (ret == -EINVAL) reg_retval = PFM_REG_RETFL_EINVAL;
 
@@ -1394,6 +1401,8 @@
 
 		/* keep track of what we use */
 		CTX_USED_PMD(ctx, pmu_conf.pmd_desc[(cnum)].dep_pmd[0]);
+		/* mark this register as used as well */
+		CTX_USED_PMD(ctx, RDEP(cnum));
 
 		/* writes to unimplemented part is ignored, so this is safe */
 		ia64_set_pmd(cnum, tmp.reg_value & pmu_conf.perf_ovfl_val);
@@ -1438,7 +1447,7 @@
 	DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid));
 
 	for (i = 0; i < count; i++, req++) {
-		unsigned long reg_val = ~0UL, ctx_val = ~0UL;
+		unsigned long ctx_val = ~0UL;
 
 		if (copy_from_user(&tmp, req, sizeof(tmp))) return -EFAULT;
 
@@ -1462,7 +1471,7 @@
 		 */
 		if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){
 			ia64_srlz_d();
-			val = reg_val = ia64_get_pmd(cnum);
+			val = ia64_get_pmd(cnum);
 			DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val));
 		} else {
 #ifdef CONFIG_SMP
@@ -1484,7 +1493,7 @@
 			}
 #endif
 			/* context has been saved */
-			val = reg_val = th->pmd[cnum];
+			val = th->pmd[cnum];
 		}
 		if (PMD_IS_COUNTING(cnum)) {
 			/*
@@ -1493,9 +1502,7 @@
 
 			val &= pmu_conf.perf_ovfl_val;
 			val += ctx_val = ctx->ctx_soft_pmds[cnum].val;
-		} else {
-			val = reg_val = ia64_get_pmd(cnum);
-		}
+		} 
 
 		tmp.reg_value = val;
 
@@ -1503,14 +1510,13 @@
 		 * execute read checker, if any
 		 */
 		if (PMD_RD_FUNC(cnum)) {
-			ret = PMD_RD_FUNC(cnum)(task, cnum, &tmp.reg_value);
+			ret = PMD_RD_FUNC(cnum)(task, cnum, &tmp.reg_value, regs);
 		}
 
 		PFM_REG_RETFLAG_SET(tmp.reg_flags, ret);
 
-		DBprintk(("read pmd[%u] ret=%d soft_pmd=0x%lx reg=0x%lx pmc=0x%lx\n", 
-					cnum, ret, ctx_val, reg_val, 
-					ia64_get_pmc(cnum)));
+		DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", 
+					cnum, ret, val, ia64_get_pmc(cnum)));
 
 		if (copy_to_user(req, &tmp, sizeof(tmp))) return -EFAULT;
 	}
@@ -1553,15 +1559,11 @@
 	 */
 	if (ctx && ctx->ctx_fl_using_dbreg == 1) return -1;
 
-	/*
-	 * XXX: not pretty
-	 */
 	LOCK_PFS();
 
 	/*
-	 * We only allow the use of debug registers when there is no system
-	 * wide monitoring 
-	 * XXX: we could relax this by 
+	 * We cannot allow setting breakpoints when system wide monitoring
+	 * sessions are using the debug registers.
 	 */
 	if (pfm_sessions.pfs_sys_use_dbregs> 0)
 		ret = -1;
@@ -1921,7 +1923,6 @@
 	dbr_mask_reg_t dbr;
 } dbreg_t;
 
-
 static int
 pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs)
 {
@@ -1963,8 +1964,8 @@
 	if (ctx->ctx_fl_system) {
 		/* we mark ourselves as owner  of the debug registers */
 		ctx->ctx_fl_using_dbreg = 1;
-	} else {
-       		if (ctx->ctx_fl_using_dbreg == 0) {
+		DBprintk(("system-wide setting fl_using_dbreg for [%d]\n", task->pid));
+	} else if (first_time) {
 			ret= -EBUSY;
 			if ((thread->flags & IA64_THREAD_DBG_VALID) != 0) {
 				DBprintk(("debug registers already in use for [%d]\n", task->pid));
@@ -1973,6 +1974,7 @@
 			/* we mark ourselves as owner  of the debug registers */
 			ctx->ctx_fl_using_dbreg = 1;
 
+			DBprintk(("setting fl_using_dbreg for [%d]\n", task->pid));
 			/* 
 			 * Given debug registers cannot be used for both debugging 
 			 * and performance monitoring at the same time, we reuse
@@ -1980,20 +1982,27 @@
 			 */
 			memset(task->thread.dbr, 0, sizeof(task->thread.dbr));
 			memset(task->thread.ibr, 0, sizeof(task->thread.ibr));
+	}
 
-			/*
-			 * clear hardware registers to make sure we don't
-			 * pick up stale state
-			 */
-			for (i=0; i < pmu_conf.num_ibrs; i++) {
-				ia64_set_ibr(i, 0UL);
-			}
-			ia64_srlz_i();
-			for (i=0; i < pmu_conf.num_dbrs; i++) {
-				ia64_set_dbr(i, 0UL);
-			}
-			ia64_srlz_d();
+	if (first_time) {
+		DBprintk(("[%d] clearing ibrs,dbrs\n", task->pid));
+		/*
+	 	 * clear hardware registers to make sure we don't
+	 	 * pick up stale state. 
+		 *
+		 * for a system wide session, we do not use
+		 * thread.dbr, thread.ibr because this process
+		 * never leaves the current CPU and the state
+		 * is shared by all processes running on it
+	 	 */
+		for (i=0; i < pmu_conf.num_ibrs; i++) {
+			ia64_set_ibr(i, 0UL);
 		}
+		ia64_srlz_i();
+		for (i=0; i < pmu_conf.num_dbrs; i++) {
+			ia64_set_dbr(i, 0UL);
+		}
+		ia64_srlz_d();
 	}
 
 	ret = -EFAULT;
@@ -2361,9 +2370,9 @@
 {
 	struct pt_regs *regs = (struct pt_regs *)&stack;
 	struct task_struct *task = current;
-	pfm_context_t *ctx = task->thread.pfm_context;
+	pfm_context_t *ctx;
 	size_t sz;
-	int ret = -ESRCH, narg;
+	int ret, narg;
 
 	/* 
 	 * reject any call if perfmon was disabled at initialization time
@@ -2393,6 +2402,8 @@
 
 		if (pid != current->pid) {
 
+			ret = -ESRCH;
+
 			read_lock(&tasklist_lock);
 
 			task = find_task_by_pid(pid);
@@ -2407,10 +2418,11 @@
 				ret = check_task_state(task);
 				if (ret != 0) goto abort_call;
 			}
-			ctx = task->thread.pfm_context;
 		}
 	} 
 
+	ctx = task->thread.pfm_context;
+
 	if (PFM_CMD_USE_CTX(cmd)) {
 		ret = -EINVAL;
 	       if (ctx == NULL) {
@@ -2953,11 +2965,6 @@
 static int
 perfmon_proc_info(char *page)
 {
-#ifdef CONFIG_SMP
-#define cpu_is_online(i) (cpu_online_map & (1UL << i))
-#else
-#define cpu_is_online(i)        1
-#endif
 	char *p = page;
 	int i;
 
@@ -4118,9 +4125,9 @@
 }
 
 static struct irqaction perfmon_irqaction = {
-	handler:	perfmon_interrupt,
-	flags:		SA_INTERRUPT,
-	name:		"perfmon"
+	.handler =	perfmon_interrupt,
+	.flags =	SA_INTERRUPT,
+	.name =		"perfmon"
 };
 
 
@@ -4150,11 +4157,6 @@
 	pal_perf_mon_info_u_t pm_info;
 	s64 status;
 
-	register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
-
-	ia64_set_pmv(IA64_PERFMON_VECTOR);
-	ia64_srlz_d();
-
 	pmu_conf.pfm_is_disabled = 1;
 
 	printk("perfmon: version %u.%u (sampling format v%u.%u) IRQ %u\n", 
@@ -4232,6 +4234,9 @@
 void
 perfmon_init_percpu (void)
 {
+	if (smp_processor_id() == 0)
+		register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction);
+
 	ia64_set_pmv(IA64_PERFMON_VECTOR);
 	ia64_srlz_d();
 }
diff -Nru a/arch/ia64/kernel/perfmon_itanium.h b/arch/ia64/kernel/perfmon_itanium.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/kernel/perfmon_itanium.h	Thu Aug  1 01:08:13 2002
@@ -0,0 +1,99 @@
+/*
+ * This file contains the Itanium PMU register description tables
+ * and pmc checker used by perfmon.c.
+ *
+ * Copyright (C) 2002  Hewlett Packard Co
+ *               Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+#define RDEP(x)	(1UL<<(x))
+
+#ifndef CONFIG_ITANIUM
+#error "This file is only valid when CONFIG_ITANIUM is defined"
+#endif
+
+static int pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
+static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs);
+
+static pfm_reg_desc_t pmc_desc[256]={
+/* pmc0  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc1  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc2  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc3  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc4  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc5  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc6  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc7  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc8  */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc9  */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc10 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, pfm_ita_pmc_check, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_ita_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+	    { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
+};
+
+static pfm_reg_desc_t pmd_desc[256]={
+/* pmd0  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
+/* pmd1  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
+/* pmd2  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
+/* pmd3  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
+/* pmd4  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
+/* pmd5  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
+/* pmd6  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
+/* pmd7  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
+/* pmd8  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd9  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
+	    { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
+};
+
+static int
+pfm_ita_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
+{
+	pfm_context_t *ctx = task->thread.pfm_context;
+	int ret;
+
+	/*
+	 * we must clear the (instruction) debug registers if pmc13.ta bit is cleared
+	 * before they are written (fl_using_dbreg==0) to avoid picking up stale information. 
+	 */
+	if (cnum == 13 && ((*val & 0x1) == 0UL) && ctx->ctx_fl_using_dbreg == 0) {
+
+		/* don't mix debug with perfmon */
+		if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
+
+		/* 
+		 * a count of 0 will mark the debug registers as in use and also
+		 * ensure that they are properly cleared.
+		 */
+		ret = pfm_write_ibr_dbr(1, task, NULL, 0, regs);
+		if (ret) return ret;
+	}
+
+	/*
+	 * we must clear the (data) debug registers if pmc11.pt bit is cleared
+	 * before they are written (fl_using_dbreg==0) to avoid picking up stale information. 
+	 */
+	if (cnum == 11 && ((*val >> 28)& 0x1) == 0 && ctx->ctx_fl_using_dbreg == 0) {
+
+		/* don't mix debug with perfmon */
+		if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
+
+		/* 
+		 * a count of 0 will mark the debug registers as in use and also
+		 * ensure that they are properly cleared.
+		 */
+		ret = pfm_write_ibr_dbr(0, task, NULL, 0, regs);
+		if (ret) return ret;
+	}
+	return 0;
+}
+
diff -Nru a/arch/ia64/kernel/perfmon_mckinley.h b/arch/ia64/kernel/perfmon_mckinley.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/kernel/perfmon_mckinley.h	Thu Aug  1 01:08:13 2002
@@ -0,0 +1,134 @@
+/*
+ * This file contains the McKinley PMU register description tables
+ * and pmc checker used by perfmon.c.
+ *
+ * Copyright (C) 2002  Hewlett Packard Co
+ *               Stephane Eranian <eranian@hpl.hp.com>
+ */
+
+#define RDEP(x)	(1UL<<(x))
+
+#ifndef CONFIG_MCKINLEY
+#error "This file is only valid when CONFIG_MCKINLEY is defined"
+#endif
+
+static int pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
+static int pfm_write_ibr_dbr(int mode, struct task_struct *task, void *arg, int count, struct pt_regs *regs);
+
+static pfm_reg_desc_t pmc_desc[256]={
+/* pmc0  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc1  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc2  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc3  */ { PFM_REG_CONTROL, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc4  */ { PFM_REG_COUNTING, 6, NULL, pfm_mck_pmc_check, {RDEP(4),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc5  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(5),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc6  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(6),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc7  */ { PFM_REG_COUNTING, 6, NULL, NULL, {RDEP(7),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc8  */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc9  */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc10 */ { PFM_REG_MONITOR, 4, NULL, NULL, {RDEP(0)|RDEP(1),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc11 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(2)|RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc12 */ { PFM_REG_MONITOR, 6, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc13 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc14 */ { PFM_REG_CONFIG, 0, NULL, pfm_mck_pmc_check, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+/* pmc15 */ { PFM_REG_CONFIG, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
+	    { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
+};
+
+static pfm_reg_desc_t pmd_desc[256]={
+/* pmd0  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(1),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
+/* pmd1  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(0),0UL, 0UL, 0UL}, {RDEP(10),0UL, 0UL, 0UL}},
+/* pmd2  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(3)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
+/* pmd3  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(17),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
+/* pmd4  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(4),0UL, 0UL, 0UL}},
+/* pmd5  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(5),0UL, 0UL, 0UL}},
+/* pmd6  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(6),0UL, 0UL, 0UL}},
+/* pmd7  */ { PFM_REG_COUNTING, 0, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {RDEP(7),0UL, 0UL, 0UL}},
+/* pmd8  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd9  */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd10 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd11 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd12 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(13)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd13 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(14)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd14 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(15)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd15 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(16),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd16 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(8)|RDEP(9)|RDEP(10)|RDEP(11)|RDEP(12)|RDEP(13)|RDEP(14)|RDEP(15),0UL, 0UL, 0UL}, {RDEP(12),0UL, 0UL, 0UL}},
+/* pmd17 */ { PFM_REG_BUFFER, 0, NULL, NULL, {RDEP(2)|RDEP(3),0UL, 0UL, 0UL}, {RDEP(11),0UL, 0UL, 0UL}},
+	    { PFM_REG_NONE, 0, NULL, NULL, {0,}, {0,}}, /* end marker */
+};
+
+static int
+pfm_mck_pmc_check(struct task_struct *task, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
+{
+	struct thread_struct *th = &task->thread;
+	pfm_context_t *ctx = task->thread.pfm_context;
+	int ret = 0, check_case1 = 0;
+	unsigned long val8 = 0, val14 = 0, val13 = 0;
+
+	/*
+	 * we must clear the debug registers if any pmc13.ena_dbrpX bit is enabled 
+	 * before they are written (fl_using_dbreg==0) to avoid picking up stale information. 
+	 */
+	if (cnum == 13 && (*val & (0xfUL << 45)) && ctx->ctx_fl_using_dbreg == 0) {
+
+		/* don't mix debug with perfmon */
+		if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
+
+		/* 
+		 * a count of 0 will mark the debug registers as in use and also
+		 * ensure that they are properly cleared.
+		 */
+		ret = pfm_write_ibr_dbr(1, task, NULL, 0, regs);
+		if (ret) return ret;
+	}
+	/* 
+	 * we must clear the (instruction) debug registers if any pmc14.ibrpX bit is enabled 
+	 * before they are (fl_using_dbreg==0) to avoid picking up stale information. 
+	 */
+	if (cnum == 14 && ((*val & 0x2222) != 0x2222) && ctx->ctx_fl_using_dbreg == 0) {
+
+		/* don't mix debug with perfmon */
+		if ((task->thread.flags & IA64_THREAD_DBG_VALID) != 0) return -EINVAL;
+
+		/* 
+		 * a count of 0 will mark the debug registers as in use and also
+		 * ensure that they are properly cleared.
+		 */
+		ret = pfm_write_ibr_dbr(0, task, NULL, 0, regs);
+		if (ret) return ret;
+
+	}
+
+	switch(cnum) {
+		case  4: *val |= 1UL << 23; /* force power enable bit */
+			 break;
+		case  8: val8 = *val;
+			 val13 = th->pmc[13];
+			 val14 = th->pmc[14];
+			 check_case1 = 1;
+			 break;
+		case 13: val8  = th->pmc[8];
+			 val13 = *val;
+			 val14 = th->pmc[14];
+			 check_case1 = 1;
+			 break;
+		case 14: val8  = th->pmc[13];
+			 val13 = th->pmc[13];
+			 val14 = *val;
+			 check_case1 = 1;
+			 break;
+	}
+	/* check illegal configuration which can produce inconsistencies in tagging
+	 * i-side events in L1D and L2 caches
+	 */
+	if (check_case1) {
+		ret =   ((val13 >> 45) & 0xf) == 0 
+		   && ((val8 & 0x1) == 0)
+		   && ((((val14>>1) & 0x3) == 0x2 || ((val14>>1) & 0x3) == 0x0)
+		       ||(((val14>>4) & 0x3) == 0x2 || ((val14>>4) & 0x3) == 0x0));
+
+		if (ret) printk("perfmon: failure check_case1\n");
+	}
+
+	return ret ? -EINVAL : 0;
+}
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/process.c	Thu Aug  1 01:08:13 2002
@@ -325,6 +325,11 @@
 
 	/* copy parts of thread_struct: */
 	p->thread.ksp = (unsigned long) child_stack - 16;
+
+	/* stop some PSR bits from being inherited: */
+	child_ptregs->cr_ipsr =  ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+				  & ~IA64_PSR_BITS_TO_CLEAR);
+
 	/*
 	 * NOTE: The calling convention considers all floating point
 	 * registers in the high partition (fph) to be scratch.  Since
diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
--- a/arch/ia64/kernel/setup.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/setup.c	Thu Aug  1 01:08:12 2002
@@ -455,10 +455,10 @@
 }
 
 struct seq_operations cpuinfo_op = {
-	start:	c_start,
-	next:	c_next,
-	stop:	c_stop,
-	show:	show_cpuinfo
+	.start =	c_start,
+	.next =		c_next,
+	.stop =		c_stop,
+	.show =		show_cpuinfo
 };
 
 void
@@ -542,7 +542,18 @@
 	extern char __per_cpu_end[];
 	int cpu = smp_processor_id();
 
-	my_cpu_data = alloc_bootmem_pages(__per_cpu_end - __per_cpu_start);
+	if (__per_cpu_end - __per_cpu_start > PAGE_SIZE)
+		panic("Per-cpu data area too big! (%Zu > %Zu)",
+		      __per_cpu_end - __per_cpu_start, PAGE_SIZE);
+
+	/*
+	 * On the BSP, the page allocator isn't initialized by the time we get here.  On
+	 * the APs, the bootmem allocator is no longer available...
+	 */
+	if (cpu == 0)
+		my_cpu_data = alloc_bootmem_pages(__per_cpu_end - __per_cpu_start);
+	else
+		my_cpu_data = (void *) get_free_page(GFP_KERNEL);
 	memcpy(my_cpu_data, __phys_per_cpu_start, __per_cpu_end - __per_cpu_start);
 	__per_cpu_offset[cpu] = (char *) my_cpu_data - __per_cpu_start;
 	my_cpu_info = my_cpu_data + ((char *) &cpu_info - __per_cpu_start);
diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
--- a/arch/ia64/kernel/signal.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/signal.c	Thu Aug  1 01:08:12 2002
@@ -146,6 +146,7 @@
 	if (from->si_code < 0) {
 		if (__copy_to_user(to, from, sizeof(siginfo_t)))
 			return -EFAULT;
+		return 0;
 	} else {
 		int err;
 
diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
--- a/arch/ia64/kernel/smpboot.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/smpboot.c	Thu Aug  1 01:08:12 2002
@@ -1,10 +1,14 @@
 /*
  * SMP boot-related support
  *
- * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  *
  * 01/05/16 Rohit Seth <rohit.seth@intel.com>	Moved SMP booting functions from smp.c to here.
  * 01/04/27 David Mosberger <davidm@hpl.hp.com>	Added ITC synching code.
+ * 02/07/31 David Mosberger <davidm@hpl.hp.com>	Switch over to hotplug-CPU boot-sequence.
+ *						smp_boot_cpus()/smp_commence() is replaced by
+ *						smp_prepare_cpus()/__cpu_up()/smp_cpus_done().
  */
 
 
@@ -66,18 +70,16 @@
 
 #define DEBUG_ITC_SYNC	0
 
-extern void __init calibrate_delay(void);
-extern void start_ap(void);
+extern void __init calibrate_delay (void);
+extern void start_ap (void);
 extern unsigned long ia64_iobase;
 
 int cpucount;
 task_t *task_for_booting_cpu;
 
-/* Setup configured maximum number of CPUs to activate */
-static int max_cpus = -1;
-
 /* Bitmask of currently online CPUs */
 volatile unsigned long cpu_online_map;
+unsigned long phys_cpu_present_map;
 
 /* which logical CPU number maps to which CPU (physical APIC ID) */
 volatile int ia64_cpu_to_sapicid[NR_CPUS];
@@ -86,44 +88,12 @@
 
 struct smp_boot_data smp_boot_data __initdata;
 
-/* Set when the idlers are all forked */
-volatile int smp_threads_ready;
-
 unsigned long ap_wakeup_vector = -1; /* External Int use to wakeup APs */
 
 char __initdata no_int_routing;
 
 unsigned char smp_int_redirect; /* are INT and IPI redirectable by the chipset? */
 
-/*
- * Setup routine for controlling SMP activation
- *
- * Command-line option of "nosmp" or "maxcpus=0" will disable SMP
- * activation entirely (the MPS table probe still happens, though).
- *
- * Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
- * greater than 0, limits the maximum number of CPUs activated in
- * SMP mode to <NUM>.
- */
-
-static int __init
-nosmp (char *str)
-{
-	max_cpus = 0;
-	return 1;
-}
-
-__setup("nosmp", nosmp);
-
-static int __init
-maxcpus (char *str)
-{
-	get_option(&str, &max_cpus);
-	return 1;
-}
-
-__setup("maxcpus=", maxcpus);
-
 static int __init
 nointroute (char *str)
 {
@@ -299,7 +269,7 @@
 
 static volatile atomic_t smp_commenced = ATOMIC_INIT(0);
 
-void __init
+static void __init
 smp_commence (void)
 {
 	/*
@@ -308,7 +278,7 @@
 	Dprintk("Setting commenced=1, go go go\n");
 
 	wmb();
-	atomic_set(&smp_commenced,1);
+	atomic_set(&smp_commenced, 1);
 }
 
 
@@ -405,6 +375,9 @@
 	int timeout, cpu;
 
 	cpu = ++cpucount;
+
+	set_bit(cpu, &phys_cpu_present_map);
+
 	/*
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
@@ -425,7 +398,7 @@
 
 	task_for_booting_cpu = idle;
 
-	Dprintk("Sending wakeup vector %u to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
+	Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
 
 	platform_send_ipi(cpu, ap_wakeup_vector, IA64_IPI_DM_INT, 0);
 
@@ -466,8 +439,8 @@
 /*
  * Cycle through the APs sending Wakeup IPIs to boot each.
  */
-void __init
-smp_boot_cpus (void)
+static void __init
+smp_boot_cpus (unsigned int max_cpus)
 {
 	int sapicid, cpu;
 	int boot_cpu_id = hard_smp_processor_id();
@@ -486,13 +459,13 @@
 	 */
 	set_bit(0, &cpu_online_map);
 	set_bit(0, &cpu_callin_map);
+	set_bit(0, &phys_cpu_present_map);
 
 	local_cpu_data->loops_per_jiffy = loops_per_jiffy;
 	ia64_cpu_to_sapicid[0] = boot_cpu_id;
 
 	printk("Boot processor id 0x%x/0x%x\n", 0, boot_cpu_id);
 
-	global_irq_holder = NO_PROC_ID;
 	current_thread_info()->cpu = 0;
 	smp_tune_scheduling();
 
@@ -537,7 +510,7 @@
 
 		printk("Before bogomips.\n");
 		if (!cpucount) {
-			printk(KERN_ERR "Error: only one processor found.\n");
+			printk(KERN_WARNING "Warning: only one processor found.\n");
 		} else {
 			unsigned long bogosum = 0;
   			for (cpu = 0; cpu < NR_CPUS; cpu++)
@@ -552,6 +525,29 @@
 	;
 }
 
+void __init
+smp_prepare_cpus (unsigned int max_cpus)
+{
+ 	smp_boot_cpus(max_cpus);
+}
+
+int __devinit
+__cpu_up (unsigned int cpu)
+{
+	/*
+	 * Yeah, that's cheesy, but it will do until there is real hotplug support and in
+	 * the meantime, this gives time for the interface changes to settle down...
+	 */
+	smp_commence();
+	return 0;
+}
+
+void __init
+smp_cpus_done (unsigned int max_cpus)
+{
+	/* nuthing... */
+}
+
 /*
  * Assume that CPU's have been discovered by some platform-dependant interface.  For
  * SoftSDV/Lion, that would be ACPI.
@@ -571,9 +567,6 @@
 	ap_startup = (struct fptr *) start_ap;
 	sal_ret = ia64_sal_set_vectors(SAL_VECTOR_OS_BOOT_RENDEZ,
 				       __pa(ap_startup->fp), __pa(ap_startup->gp), 0, 0, 0, 0);
-	if (sal_ret < 0) {
-		printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n     Forcing UP mode\n",
-		       ia64_sal_strerror(sal_ret));
-		max_cpus = 0;
-	}
+	if (sal_ret < 0)
+		printk("SMP: Can't set SAL AP Boot Rendezvous: %s\n", ia64_sal_strerror(sal_ret));
 }
diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
--- a/arch/ia64/kernel/sys_ia64.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/sys_ia64.c	Thu Aug  1 01:08:13 2002
@@ -82,7 +82,6 @@
 ia64_shmat (int shmid, void *shmaddr, int shmflg, long arg3, long arg4, long arg5, long arg6,
 	    long arg7, long stack)
 {
-	extern int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr);
 	struct pt_regs *regs = (struct pt_regs *) &stack;
 	unsigned long raddr;
 	int retval;
@@ -120,7 +119,7 @@
 
 	/* Always allow shrinking brk. */
 	if (brk <= mm->brk) {
-		if (!do_munmap(mm, newbrk, oldbrk-newbrk))
+		if (!do_munmap(mm, newbrk, oldbrk-newbrk, 1))
 			goto set_brk;
 		goto out;
 	}
@@ -136,10 +135,6 @@
 
 	/* Check against existing mmap mappings. */
 	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. */
diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
--- a/arch/ia64/kernel/time.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/kernel/time.c	Thu Aug  1 01:08:12 2002
@@ -41,21 +41,22 @@
 	extern unsigned long prof_cpu_mask;
 	extern char _stext;
 
+	if (!prof_buffer)
+		return;
+
 	if (!((1UL << smp_processor_id()) & prof_cpu_mask))
 		return;
 
-	if (prof_buffer && current->pid) {
-		ip -= (unsigned long) &_stext;
-		ip >>= prof_shift;
-		/*
-		 * Don't ignore out-of-bounds IP values silently, put them into the last
-		 * histogram slot, so if present, they will show up as a sharp peak.
-		 */
-		if (ip > prof_len - 1)
-			ip = prof_len - 1;
+	ip -= (unsigned long) &_stext;
+	ip >>= prof_shift;
+	/*
+	 * Don't ignore out-of-bounds IP values silently, put them into the last
+	 * histogram slot, so if present, they will show up as a sharp peak.
+	 */
+	if (ip > prof_len - 1)
+		ip = prof_len - 1;
 
-		atomic_inc((atomic_t *) &prof_buffer[ip]);
-	}
+	atomic_inc((atomic_t *) &prof_buffer[ip]);
 }
 
 /*
@@ -285,9 +286,9 @@
 }
 
 static struct irqaction timer_irqaction = {
-	handler:	timer_interrupt,
-	flags:		SA_INTERRUPT,
-	name:		"timer"
+	.handler =	timer_interrupt,
+	.flags =	SA_INTERRUPT,
+	.name =		"timer"
 };
 
 void __init
diff -Nru a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
--- a/arch/ia64/kernel/traps.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/traps.c	Thu Aug  1 01:08:13 2002
@@ -62,27 +62,26 @@
 void
 bust_spinlocks (int yes)
 {
+	int loglevel_save = console_loglevel;
+
 	spin_lock_init(&timerlist_lock);
 	if (yes) {
 		oops_in_progress = 1;
-#ifdef CONFIG_SMP
-		global_irq_lock = 0;	/* Many serial drivers do __global_cli() */
-#endif
-	} else {
-		int loglevel_save = console_loglevel;
+		return;
+	}
+
 #ifdef CONFIG_VT
-		unblank_screen();
+	unblank_screen();
 #endif
-		oops_in_progress = 0;
-		/*
-		 * OK, the message is on the console.  Now we call printk() without
-		 * oops_in_progress set so that printk will give klogd a poke.  Hold onto
-		 * your hats...
-		 */
-		console_loglevel = 15;		/* NMI oopser may have shut the console up */
-		printk(" ");
-		console_loglevel = loglevel_save;
-	}
+	oops_in_progress = 0;
+	/*
+	 * OK, the message is on the console.  Now we call printk() without
+	 * oops_in_progress set so that printk will give klogd a poke.  Hold onto
+	 * your hats...
+	 */
+	console_loglevel = 15;		/* NMI oopser may have shut the console up */
+	printk(" ");
+	console_loglevel = loglevel_save;
 }
 
 void
@@ -93,9 +92,9 @@
 		int lock_owner;
 		int lock_owner_depth;
 	} die = {
-		lock:			SPIN_LOCK_UNLOCKED,
-		lock_owner:		-1,
-		lock_owner_depth:	0
+		.lock =			SPIN_LOCK_UNLOCKED,
+		.lock_owner =		-1,
+		.lock_owner_depth =	0
 	};
 
 	if (die.lock_owner != smp_processor_id()) {
@@ -435,7 +434,7 @@
 	unsigned long code, error = isr;
 	struct siginfo siginfo;
 	char buf[128];
-	int result;
+	int result, sig;
 	static const char *reason[] = {
 		"IA-64 Illegal Operation fault",
 		"IA-64 Privileged Operation fault",
@@ -479,6 +478,30 @@
 		break;
 
 	      case 26: /* NaT Consumption */
+		if (user_mode(regs)) {
+			if (((isr >> 4) & 0xf) == 2) {
+				/* NaT page consumption */
+				sig = SIGSEGV;
+				code = SEGV_ACCERR;
+			} else {
+				/* register NaT consumption */
+				sig = SIGILL;
+				code = ILL_ILLOPN;
+			}
+			siginfo.si_signo = sig;
+			siginfo.si_code = code;
+			siginfo.si_errno = 0;
+			siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);
+			siginfo.si_imm = vector;
+			siginfo.si_flags = __ISR_VALID;
+			siginfo.si_isr = isr;
+			force_sig_info(sig, &siginfo, current);
+			return;
+		} else if (done_with_exception(regs))
+			return;
+		sprintf(buf, "NaT consumption");
+		break;
+
 	      case 31: /* Unsupported Data Reference */
 		if (user_mode(regs)) {
 			siginfo.si_signo = SIGILL;
@@ -491,7 +514,7 @@
 			force_sig_info(SIGILL, &siginfo, current);
 			return;
 		}
-		sprintf(buf, (vector == 26) ? "NaT consumption" : "Unsupported data reference");
+		sprintf(buf, "Unsupported data reference");
 		break;
 
 	      case 29: /* Debug */
@@ -508,16 +531,15 @@
 			if (ia64_psr(regs)->is == 0)
 			  ifa = regs->cr_iip;
 #endif
-			siginfo.si_addr = (void *) ifa;
 			break;
-		      case 35: siginfo.si_code = TRAP_BRANCH; break;
-		      case 36: siginfo.si_code = TRAP_TRACE; break;
+		      case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
+		      case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
 		}
 		siginfo.si_signo = SIGTRAP;
 		siginfo.si_errno = 0;
 		siginfo.si_flags = 0;
 		siginfo.si_isr = 0;
-		siginfo.si_addr = 0;
+		siginfo.si_addr = (void *) ifa;
 		siginfo.si_imm = 0;
 		force_sig_info(SIGTRAP, &siginfo, current);
 		return;
diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
--- a/arch/ia64/kernel/unwind.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/kernel/unwind.c	Thu Aug  1 01:08:13 2002
@@ -140,13 +140,13 @@
 	} stat;
 # endif
 } unw = {
-	tables: &unw.kernel_table,
-	lock: SPIN_LOCK_UNLOCKED,
-	save_order: {
+	.tables = &unw.kernel_table,
+	.lock = SPIN_LOCK_UNLOCKED,
+	.save_order = {
 		UNW_REG_RP, UNW_REG_PFS, UNW_REG_PSP, UNW_REG_PR,
 		UNW_REG_UNAT, UNW_REG_LC, UNW_REG_FPSR, UNW_REG_PRI_UNAT_GR
 	},
-	preg_index: {
+	.preg_index = {
 		struct_offset(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_GR */
 		struct_offset(struct unw_frame_info, pri_unat_loc)/8,	/* PRI_UNAT_MEM */
 		struct_offset(struct unw_frame_info, bsp_loc)/8,
@@ -189,9 +189,9 @@
 		struct_offset(struct unw_frame_info, fr_loc[30 - 16])/8,
 		struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8,
 	},
-	hash : { [0 ... UNW_HASH_SIZE - 1] = -1 },
+	.hash = { [0 ... UNW_HASH_SIZE - 1] = -1 },
 #if UNW_DEBUG
-	preg_name: {
+	.preg_name = {
 		"pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp",
 		"r4", "r5", "r6", "r7",
 		"ar.unat", "pr", "ar.lc", "ar.fpsr",
@@ -634,8 +634,8 @@
 	for (reg = hi; reg >= lo; --reg) {
 		if (reg->where == UNW_WHERE_SPILL_HOME) {
 			reg->where = UNW_WHERE_PSPREL;
-			reg->val = 0x10 - *offp;
-			*offp += regsize;
+			*offp -= regsize;
+			reg->val = *offp;
 		}
 	}
 }
@@ -814,7 +814,8 @@
 	}
 	for (i = 0; i < 20; ++i) {
 		if ((frmask & 1) != 0) {
-			set_reg(sr->curr.reg + UNW_REG_F2 + i, UNW_WHERE_SPILL_HOME,
+			int base = (i < 4) ? UNW_REG_F2 : UNW_REG_F16 - 4;
+			set_reg(sr->curr.reg + base + i, UNW_WHERE_SPILL_HOME,
 				sr->region_start + sr->region_len - 1, 0);
 			sr->any_spills = 1;
 		}
diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile
--- a/arch/ia64/lib/Makefile	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/lib/Makefile	Thu Aug  1 01:08:13 2002
@@ -6,43 +6,51 @@
 
 export-objs := io.o swiotlb.o
 
-obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o					\
-	__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o					\
-	checksum.o clear_page.o csum_partial_copy.o copy_page.o				\
-	copy_user.o clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o	\
-	flush.o io.o ip_fast_csum.o do_csum.o						\
-	memcpy.o memset.o strlen.o swiotlb.o
+obj-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o			\
+	__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o			\
+	checksum.o clear_page.o csum_partial_copy.o copy_page.o		\
+	clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o	\
+	flush.o io.o ip_fast_csum.o do_csum.o				\
+	memset.o strlen.o swiotlb.o
 
-obj-$(CONFIG_ITANIUM) += copy_page.o
-obj-$(CONFIG_MCKINLEY) += copy_page_mck.o
+obj-$(CONFIG_ITANIUM)	+= copy_page.o copy_user.o memcpy.o
+obj-$(CONFIG_MCKINLEY)	+= copy_page_mck.o memcpy_mck.o
 
 IGNORE_FLAGS_OBJS =	__divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \
 			__divdi3.o __udivdi3.o __moddi3.o __umoddi3.o
 
-$(L_TARGET): $(obj-y) $(export-objs)
+include $(TOPDIR)/Rules.make
+
+AFLAGS___divdi3.o	=
+AFLAGS___udivdi3.o	= -DUNSIGNED
+AFLAGS___moddi3.o	= 	     -DMODULO
+AFLAGS___umoddi3.o	= -DUNSIGNED -DMODULO
+
+AFLAGS___divsi3.o	=
+AFLAGS___udivsi3.o	= -DUNSIGNED
+AFLAGS___modsi3.o	=	     -DMODULO
+AFLAGS___umodsi3.o	= -DUNSIGNED -DMODULO
 
 __divdi3.o: idiv64.S
-	$(CC) $(AFLAGS) -c -o $@ $<
+	$(cmd_as_o_S)
 
 __udivdi3.o: idiv64.S
-	$(CC) $(AFLAGS) -c -DUNSIGNED -c -o $@ $<
+	$(cmd_as_o_S)
 
 __moddi3.o: idiv64.S
-	$(CC) $(AFLAGS) -c -DMODULO -c -o $@ $<
+	$(cmd_as_o_S)
 
 __umoddi3.o: idiv64.S
-	$(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -c -o $@ $<
+	$(cmd_as_o_S)
 
 __divsi3.o: idiv32.S
-	$(CC) $(AFLAGS) -c -o $@ $<
+	$(cmd_as_o_S)
 
 __udivsi3.o: idiv32.S
-	$(CC) $(AFLAGS) -c -DUNSIGNED -c -o $@ $<
+	$(cmd_as_o_S)
 
 __modsi3.o: idiv32.S
-	$(CC) $(AFLAGS) -c -DMODULO -c -o $@ $<
+	$(cmd_as_o_S)
 
 __umodsi3.o: idiv32.S
-	$(CC) $(AFLAGS) -c -DMODULO -DUNSIGNED -c -o $@ $<
-
-include $(TOPDIR)/Rules.make
+	$(cmd_as_o_S)
diff -Nru a/arch/ia64/lib/copy_user.S b/arch/ia64/lib/copy_user.S
--- a/arch/ia64/lib/copy_user.S	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/lib/copy_user.S	Thu Aug  1 01:08:12 2002
@@ -237,15 +237,17 @@
 .copy_user_bit##rshift:						\
 1:								\
 	EX(.failure_out,(EPI) st8 [dst1]=tmp,8);		\
-(EPI_1) shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift;	\
-	EX(3f,(p16) ld8 val1[0]=[src1],8);			\
+(EPI_1) shrp tmp=val1[PIPE_DEPTH-2],val1[PIPE_DEPTH-1],rshift;	\
+	EX(3f,(p16) ld8 val1[1]=[src1],8);			\
+(p16)	mov val1[0]=r0;						\
 	br.ctop.dptk 1b;					\
 	;;							\
 	br.cond.sptk.many .diff_align_do_tail;			\
 2:								\
 (EPI)	st8 [dst1]=tmp,8;					\
-(EPI_1)	shrp tmp=val1[PIPE_DEPTH-3],val1[PIPE_DEPTH-2],rshift;	\
+(EPI_1)	shrp tmp=val1[PIPE_DEPTH-2],val1[PIPE_DEPTH-1],rshift;	\
 3:								\
+(p16)	mov val1[1]=r0;						\
 (p16)	mov val1[0]=r0;						\
 	br.ctop.dptk 2b;					\
 	;;							\
diff -Nru a/arch/ia64/lib/io.c b/arch/ia64/lib/io.c
--- a/arch/ia64/lib/io.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/lib/io.c	Thu Aug  1 01:08:12 2002
@@ -87,6 +87,12 @@
 	__ia64_outl(val, port);
 }
 
+void
+ia64_mmiob (void)
+{
+	__ia64_mmiob();
+}
+
 /* define aliases: */
 
 asm (".global __ia64_inb, __ia64_inw, __ia64_inl");
@@ -98,5 +104,8 @@
 asm ("__ia64_outb = ia64_outb");
 asm ("__ia64_outw = ia64_outw");
 asm ("__ia64_outl = ia64_outl");
+
+asm (".global __ia64_mmiob");
+asm ("__ia64_mmiob = ia64_mmiob");
 
 #endif /* CONFIG_IA64_GENERIC */
diff -Nru a/arch/ia64/lib/memcpy_mck.S b/arch/ia64/lib/memcpy_mck.S
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/arch/ia64/lib/memcpy_mck.S	Thu Aug  1 01:08:13 2002
@@ -0,0 +1,674 @@
+/*
+ * Itanium 2-optimized version of memcpy and copy_user function
+ *
+ * Inputs:
+ * 	in0:	destination address
+ *	in1:	source address
+ *	in2:	number of bytes to copy
+ * Output:
+ * 	0 if success, or number of byte NOT copied if error occurred.
+ *
+ * Copyright (C) 2002 Intel Corp.
+ * Copyright (C) 2002 Ken Chen <kenneth.w.chen@intel.com>
+ */
+#include <linux/config.h>
+#include <asm/asmmacro.h>
+#include <asm/page.h>
+
+#if __GNUC__ >= 3
+# define EK(y...) EX(y)
+#else
+# define EK(y,x...)  x
+#endif
+
+GLOBAL_ENTRY(bcopy)
+	.regstk 3,0,0,0
+	mov r8=in0
+	mov in0=in1
+	;;
+	mov in1=r8
+	;;
+END(bcopy)
+
+/* McKinley specific optimization */
+
+#define retval		r8
+#define saved_pfs	r31
+#define saved_lc	r10
+#define saved_pr	r11
+#define saved_in0	r14
+#define saved_in1	r15
+#define saved_in2	r16
+
+#define src0		r2
+#define src1		r3
+#define dst0		r17
+#define dst1		r18
+#define cnt		r9
+
+/* r19-r30 are temp for each code section */
+#define PREFETCH_DIST	8
+#define src_pre_mem	r19
+#define dst_pre_mem	r20
+#define src_pre_l2	r21
+#define dst_pre_l2	r22
+#define t1		r23
+#define t2		r24
+#define t3		r25
+#define t4		r26
+#define t5		t1	// alias!
+#define t6		t2	// alias!
+#define t7		t3	// alias!
+#define n8		r27
+#define t9		t5	// alias!
+#define t10		t4	// alias!
+#define t11		t7	// alias!
+#define t12		t6	// alias!
+#define t14		t10	// alias!
+#define t13		r28
+#define t15		r29
+#define tmp		r30
+
+/* defines for long_copy block */
+#define	A	0
+#define B	(PREFETCH_DIST)
+#define C	(B + PREFETCH_DIST)
+#define D	(C + 1)
+#define N	(D + 1)
+#define Nrot	((N + 7) & ~7)
+
+/* alias */
+#define in0		r32
+#define in1		r33
+#define in2		r34
+
+GLOBAL_ENTRY(memcpy)
+	and	r28=0x7,in0
+	and	r29=0x7,in1
+	mov	f6=f0
+	br.cond.sptk .common_code
+	;;
+GLOBAL_ENTRY(__copy_user)
+	.prologue
+// check dest alignment
+	and	r28=0x7,in0
+	and	r29=0x7,in1
+	mov	f6=f1
+	mov	saved_in0=in0	// save dest pointer
+	mov	saved_in1=in1	// save src pointer
+	mov	saved_in2=in2	// save len
+	;;
+.common_code:
+	cmp.gt	p15,p0=8,in2	// check for small size
+	cmp.ne	p13,p0=0,r28	// check dest alignment
+	cmp.ne	p14,p0=0,r29	// check src alignment
+	add	src0=0,in1
+	sub	r30=8,r28	// for .align_dest
+	mov	retval=r0	// initialize return value
+	;;
+	add	dst0=0,in0
+	add	dst1=1,in0	// dest odd index
+	cmp.le	p6,p0 = 1,r30	// for .align_dest
+(p15)	br.cond.dpnt .memcpy_short
+(p13)	br.cond.dpnt .align_dest
+(p14)	br.cond.dpnt .unaligned_src
+	;;
+
+// both dest and src are aligned on 8-byte boundary
+.aligned_src:
+	.save ar.pfs, saved_pfs
+	alloc	saved_pfs=ar.pfs,3,Nrot-3,0,Nrot
+	.save pr, saved_pr
+	mov	saved_pr=pr
+
+	shr.u	cnt=in2,7	// this much cache line
+	;;
+	cmp.lt	p6,p0=2*PREFETCH_DIST,cnt
+	cmp.lt	p7,p8=1,cnt
+	.save ar.lc, saved_lc
+	mov	saved_lc=ar.lc
+	.body
+	add	cnt=-1,cnt
+	add	src_pre_mem=0,in1	// prefetch src pointer
+	add	dst_pre_mem=0,in0	// prefetch dest pointer
+	;;
+(p7)	mov	ar.lc=cnt	// prefetch count
+(p8)	mov	ar.lc=r0
+(p6)	br.cond.dpnt .long_copy
+	;;
+
+.prefetch:
+	lfetch.fault	  [src_pre_mem], 128
+	lfetch.fault.excl [dst_pre_mem], 128
+	br.cloop.dptk.few .prefetch
+	;;
+
+.medium_copy:
+	and	tmp=31,in2	// copy length after iteration
+	shr.u	r29=in2,5	// number of 32-byte iteration
+	add	dst1=8,dst0	// 2nd dest pointer
+	;;
+	add	cnt=-1,r29	// ctop iteration adjustment
+	cmp.eq	p10,p0=r29,r0	// do we really need to loop?
+	add	src1=8,src0	// 2nd src pointer
+	cmp.le	p6,p0=8,tmp
+	;;
+	cmp.le	p7,p0=16,tmp
+	mov	ar.lc=cnt	// loop setup
+	cmp.eq	p16,p17 = r0,r0
+	mov	ar.ec=2
+(p10)	br.dpnt.few .aligned_src_tail
+	;;
+	.align 32
+1:
+EX(.ex_handler, (p16)	ld8	r34=[src0],16)
+EK(.ex_handler, (p16)	ld8	r38=[src1],16)
+EX(.ex_handler, (p17)	st8	[dst0]=r33,16)
+EK(.ex_handler, (p17)	st8	[dst1]=r37,16)
+	;;
+EX(.ex_handler, (p16)	ld8	r32=[src0],16)
+EK(.ex_handler, (p16)	ld8	r36=[src1],16)
+EX(.ex_handler, (p16)	st8	[dst0]=r34,16)
+EK(.ex_handler, (p16)	st8	[dst1]=r38,16)
+	br.ctop.dptk.few 1b
+	;;
+
+.aligned_src_tail:
+EX(.ex_handler, (p6)	ld8	t1=[src0])
+	mov	ar.lc=saved_lc
+	mov	ar.pfs=saved_pfs
+EX(.ex_hndlr_s, (p7)	ld8	t2=[src1],8)
+	cmp.le	p8,p0=24,tmp
+	and	r21=-8,tmp
+	;;
+EX(.ex_hndlr_s, (p8)	ld8	t3=[src1])
+EX(.ex_handler, (p6)	st8	[dst0]=t1)	// store byte 1
+	and	in2=7,tmp	// remaining length
+EX(.ex_hndlr_d, (p7)	st8	[dst1]=t2,8)	// store byte 2
+	add	src0=src0,r21	// setting up src pointer
+	add	dst0=dst0,r21	// setting up dest pointer
+	;;
+EX(.ex_handler, (p8)	st8	[dst1]=t3)	// store byte 3
+	mov	pr=saved_pr,-1
+	br.dptk.many .memcpy_short
+	;;
+
+/* code taken from copy_page_mck */
+.long_copy:
+	.rotr v[2*PREFETCH_DIST]
+	.rotp p[N]
+
+	mov src_pre_mem = src0
+	mov pr.rot = 0x10000
+	mov ar.ec = 1				// special unrolled loop
+
+	mov dst_pre_mem = dst0
+
+	add src_pre_l2 = 8*8, src0
+	add dst_pre_l2 = 8*8, dst0
+	;;
+	add src0 = 8, src_pre_mem		// first t1 src
+	mov ar.lc = 2*PREFETCH_DIST - 1
+	shr.u cnt=in2,7				// number of lines
+	add src1 = 3*8, src_pre_mem		// first t3 src
+	add dst0 = 8, dst_pre_mem		// first t1 dst
+	add dst1 = 3*8, dst_pre_mem		// first t3 dst
+	;;
+	and tmp=127,in2				// remaining bytes after this block
+	add cnt = -(2*PREFETCH_DIST) - 1, cnt
+	// same as .line_copy loop, but with all predicated-off instructions removed:
+.prefetch_loop:
+EX(.ex_hndlr_lcpy_1, (p[A])	ld8 v[A] = [src_pre_mem], 128)		// M0
+EK(.ex_hndlr_lcpy_1, (p[B])	st8 [dst_pre_mem] = v[B], 128)		// M2
+	br.ctop.sptk .prefetch_loop
+	;;
+	cmp.eq p16, p0 = r0, r0			// reset p16 to 1
+	mov ar.lc = cnt
+	mov ar.ec = N				// # of stages in pipeline
+	;;
+.line_copy:
+EX(.ex_handler,	(p[D])	ld8 t2 = [src0], 3*8)			// M0
+EK(.ex_handler,	(p[D])	ld8 t4 = [src1], 3*8)			// M1
+EX(.ex_handler_lcpy,	(p[B])	st8 [dst_pre_mem] = v[B], 128)		// M2 prefetch dst from memory
+EK(.ex_handler_lcpy,	(p[D])	st8 [dst_pre_l2] = n8, 128)		// M3 prefetch dst from L2
+	;;
+EX(.ex_handler_lcpy,	(p[A])	ld8 v[A] = [src_pre_mem], 128)		// M0 prefetch src from memory
+EK(.ex_handler_lcpy,	(p[C])	ld8 n8 = [src_pre_l2], 128)		// M1 prefetch src from L2
+EX(.ex_handler,	(p[D])	st8 [dst0] =  t1, 8)			// M2
+EK(.ex_handler,	(p[D])	st8 [dst1] =  t3, 8)			// M3
+	;;
+EX(.ex_handler,	(p[D])	ld8  t5 = [src0], 8)
+EK(.ex_handler,	(p[D])	ld8  t7 = [src1], 3*8)
+EX(.ex_handler,	(p[D])	st8 [dst0] =  t2, 3*8)
+EK(.ex_handler,	(p[D])	st8 [dst1] =  t4, 3*8)
+	;;
+EX(.ex_handler,	(p[D])	ld8  t6 = [src0], 3*8)
+EK(.ex_handler,	(p[D])	ld8 t10 = [src1], 8)
+EX(.ex_handler,	(p[D])	st8 [dst0] =  t5, 8)
+EK(.ex_handler,	(p[D])	st8 [dst1] =  t7, 3*8)
+	;;
+EX(.ex_handler,	(p[D])	ld8  t9 = [src0], 3*8)
+EK(.ex_handler,	(p[D])	ld8 t11 = [src1], 3*8)
+EX(.ex_handler,	(p[D])	st8 [dst0] =  t6, 3*8)
+EK(.ex_handler,	(p[D])	st8 [dst1] = t10, 8)
+	;;
+EX(.ex_handler,	(p[D])	ld8 t12 = [src0], 8)
+EK(.ex_handler,	(p[D])	ld8 t14 = [src1], 8)
+EX(.ex_handler,	(p[D])	st8 [dst0] =  t9, 3*8)
+EK(.ex_handler,	(p[D])	st8 [dst1] = t11, 3*8)
+	;;
+EX(.ex_handler,	(p[D])	ld8 t13 = [src0], 4*8)
+EK(.ex_handler,	(p[D])	ld8 t15 = [src1], 4*8)
+EX(.ex_handler,	(p[D])	st8 [dst0] = t12, 8)
+EK(.ex_handler,	(p[D])	st8 [dst1] = t14, 8)
+	;;
+EX(.ex_handler,	(p[C])	ld8  t1 = [src0], 8)
+EK(.ex_handler,	(p[C])	ld8  t3 = [src1], 8)
+EX(.ex_handler,	(p[D])	st8 [dst0] = t13, 4*8)
+EK(.ex_handler,	(p[D])	st8 [dst1] = t15, 4*8)
+	br.ctop.sptk .line_copy
+	;;
+
+	add dst0=-8,dst0
+	add src0=-8,src0
+	mov in2=tmp
+	.restore sp
+	br.sptk.many .medium_copy
+	;;
+
+#define BLOCK_SIZE	128*32
+#define blocksize	r23
+#define curlen		r24
+
+// dest is on 8-byte boundary, src is not. We need to do
+// ld8-ld8, shrp, then st8.  Max 8 byte copy per cycle.
+.unaligned_src:
+	.prologue
+	.save ar.pfs, saved_pfs
+	alloc	saved_pfs=ar.pfs,3,5,0,8
+	.save ar.lc, saved_lc
+	mov	saved_lc=ar.lc
+	.save pr, saved_pr
+	mov	saved_pr=pr
+	.body
+.4k_block:
+	mov	saved_in0=dst0	// need to save all input arguments
+	mov	saved_in2=in2
+	mov	blocksize=BLOCK_SIZE
+	;;
+	cmp.lt	p6,p7=blocksize,in2
+	mov	saved_in1=src0
+	;;
+(p6)	mov	in2=blocksize
+	;;
+	shr.u	r21=in2,7	// this much cache line
+	shr.u	r22=in2,4	// number of 16-byte iteration
+	and	curlen=15,in2	// copy length after iteration
+	and	r30=7,src0	// source alignment
+	;;
+	cmp.lt	p7,p8=1,r21
+	add	cnt=-1,r21
+	;;
+
+	add	src_pre_mem=0,src0	// prefetch src pointer
+	add	dst_pre_mem=0,dst0	// prefetch dest pointer
+	and	src0=-8,src0		// 1st src pointer
+(p7)	mov	ar.lc = r21
+(p8)	mov	ar.lc = r0
+	;;
+	.align 32
+1:	lfetch.fault	  [src_pre_mem], 128
+	lfetch.fault.excl [dst_pre_mem], 128
+	br.cloop.dptk.few 1b
+	;;
+
+	shladd	dst1=r22,3,dst0	// 2nd dest pointer
+	shladd	src1=r22,3,src0	// 2nd src pointer
+	cmp.eq	p8,p9=r22,r0	// do we really need to loop?
+	cmp.le	p6,p7=8,curlen;	// have at least 8 byte remaining?
+	add	cnt=-1,r22	// ctop iteration adjustment
+	;;
+EX(.ex_handler, (p9)	ld8	r33=[src0],8)	// loop primer
+EK(.ex_handler, (p9)	ld8	r37=[src1],8)
+(p8)	br.dpnt.few .noloop
+	;;
+
+// The jump address is calculated based on src alignment. The COPYU
+// macro below need to confine its size to power of two, so an entry
+// can be caulated using shl instead of an expensive multiply. The
+// size is then hard coded by the following #define to match the
+// actual size.  This make it somewhat tedious when COPYU macro gets
+// changed and this need to be adjusted to match.
+#define LOOP_SIZE 6
+1:
+	mov	r29=ip		// jmp_table thread
+	mov	ar.lc=cnt
+	;;
+	add	r29=.jump_table - 1b - (.jmp1-.jump_table), r29
+	shl	r28=r30, LOOP_SIZE	// jmp_table thread
+	mov	ar.ec=2		// loop setup
+	;;
+	add	r29=r29,r28		// jmp_table thread
+	cmp.eq	p16,p17=r0,r0
+	;;
+	mov	b6=r29			// jmp_table thread
+	;;
+	br.cond.sptk.few b6
+
+// for 8-15 byte case
+// We will skip the loop, but need to replicate the side effect
+// that the loop produces.
+.noloop:
+EX(.ex_handler, (p6)	ld8	r37=[src1],8)
+	add	src0=8,src0
+(p6)	shl	r25=r30,3
+	;;
+EX(.ex_handler, (p6)	ld8	r27=[src1])
+(p6)	shr.u	r28=r37,r25
+(p6)	sub	r26=64,r25
+	;;
+(p6)	shl	r27=r27,r26
+	;;
+(p6)	or	r21=r28,r27
+
+.unaligned_src_tail:
+/* check if we have more than blocksize to copy, if so go back */
+	cmp.gt	p8,p0=saved_in2,blocksize
+	;;
+(p8)	add	dst0=saved_in0,blocksize
+(p8)	add	src0=saved_in1,blocksize
+(p8)	sub	in2=saved_in2,blocksize
+(p8)	br.dpnt	.4k_block
+	;;
+
+/* we have up to 15 byte to copy in the tail.
+ * part of work is already done in the jump table code
+ * we are at the following state.
+ * src side:
+ * 
+ *   xxxxxx xx                   <----- r21 has xxxxxxxx already
+ * -------- -------- --------
+ * 0        8        16
+ *          ^
+ *          |
+ *          src1
+ * 
+ * dst
+ * -------- -------- --------
+ * ^
+ * |
+ * dst1
+ */
+EX(.ex_handler, (p6)	st8	[dst1]=r21,8)	// more than 8 byte to copy
+(p6)	add	curlen=-8,curlen	// update length
+	mov	ar.pfs=saved_pfs
+	;;
+	mov	ar.lc=saved_lc
+	mov	pr=saved_pr,-1
+	mov	in2=curlen	// remaining length
+	mov	dst0=dst1	// dest pointer
+	add	src0=src1,r30	// forward by src alignment
+	;;
+
+// 7 byte or smaller.
+.memcpy_short:
+	cmp.le	p8,p9   = 1,in2
+	cmp.le	p10,p11 = 2,in2
+	cmp.le	p12,p13 = 3,in2
+	cmp.le	p14,p15 = 4,in2
+	add	src1=1,src0	// second src pointer
+	add	dst1=1,dst0	// second dest pointer
+	;;
+
+EX(.ex_handler_short, (p8)	ld1	t1=[src0],2)
+EK(.ex_handler_short, (p10)	ld1	t2=[src1],2)
+(p9)	br.ret.dpnt rp		// 0 byte copy
+	;;
+
+EX(.ex_handler_short, (p8)	st1	[dst0]=t1,2)
+EK(.ex_handler_short, (p10)	st1	[dst1]=t2,2)
+(p11)	br.ret.dpnt rp		// 1 byte copy
+
+EX(.ex_handler_short, (p12)	ld1	t3=[src0],2)
+EK(.ex_handler_short, (p14)	ld1	t4=[src1],2)
+(p13)	br.ret.dpnt rp		// 2 byte copy
+	;;
+
+	cmp.le	p6,p7   = 5,in2
+	cmp.le	p8,p9   = 6,in2
+	cmp.le	p10,p11 = 7,in2
+
+EX(.ex_handler_short, (p12)	st1	[dst0]=t3,2)
+EK(.ex_handler_short, (p14)	st1	[dst1]=t4,2)
+(p15)	br.ret.dpnt rp		// 3 byte copy
+	;;
+
+EX(.ex_handler_short, (p6)	ld1	t5=[src0],2)
+EK(.ex_handler_short, (p8)	ld1	t6=[src1],2)
+(p7)	br.ret.dpnt rp		// 4 byte copy
+	;;
+
+EX(.ex_handler_short, (p6)	st1	[dst0]=t5,2)
+EK(.ex_handler_short, (p8)	st1	[dst1]=t6,2)
+(p9)	br.ret.dptk rp		// 5 byte copy
+
+EX(.ex_handler_short, (p10)	ld1	t7=[src0],2)
+(p11)	br.ret.dptk rp		// 6 byte copy
+	;;
+
+EX(.ex_handler_short, (p10)	st1	[dst0]=t7,2)
+	br.ret.dptk rp		// done all cases
+
+
+/* Align dest to nearest 8-byte boundary. We know we have at
+ * least 7 bytes to copy, enough to crawl to 8-byte boundary.
+ * Actual number of byte to crawl depend on the dest alignment.
+ * 7 byte or less is taken care at .memcpy_short
+
+ * src0 - source even index
+ * src1 - source  odd index
+ * dst0 - dest even index
+ * dst1 - dest  odd index
+ * r30  - distance to 8-byte boundary
+ */
+
+.align_dest:
+	add	src1=1,in1	// source odd index
+	cmp.le	p7,p0 = 2,r30	// for .align_dest
+	cmp.le	p8,p0 = 3,r30	// for .align_dest
+EX(.ex_handler_short, (p6)	ld1	t1=[src0],2)
+	cmp.le	p9,p0 = 4,r30	// for .align_dest
+	cmp.le	p10,p0 = 5,r30
+	;;
+EX(.ex_handler_short, (p7)	ld1	t2=[src1],2)
+EK(.ex_handler_short, (p8)	ld1	t3=[src0],2)
+	cmp.le	p11,p0 = 6,r30
+EX(.ex_handler_short, (p6)	st1	[dst0] = t1,2)
+	cmp.le	p12,p0 = 7,r30
+	;;
+EX(.ex_handler_short, (p9)	ld1	t4=[src1],2)
+EK(.ex_handler_short, (p10)	ld1	t5=[src0],2)
+EX(.ex_handler_short, (p7)	st1	[dst1] = t2,2)
+EK(.ex_handler_short, (p8)	st1	[dst0] = t3,2)
+	;;
+EX(.ex_handler_short, (p11)	ld1	t6=[src1],2)
+EK(.ex_handler_short, (p12)	ld1	t7=[src0],2)
+	cmp.eq	p6,p7=r28,r29
+EX(.ex_handler_short, (p9)	st1	[dst1] = t4,2)
+EK(.ex_handler_short, (p10)	st1	[dst0] = t5,2)
+	sub	in2=in2,r30
+	;;
+EX(.ex_handler_short, (p11)	st1	[dst1] = t6,2)
+EK(.ex_handler_short, (p12)	st1	[dst0] = t7)
+	add	dst0=in0,r30	// setup arguments
+	add	src0=in1,r30
+(p6)	br.cond.dptk .aligned_src
+(p7)	br.cond.dpnt .unaligned_src
+	;;
+
+/* main loop body in jump table format */
+#define COPYU(shift)									\
+1:											\
+EX(.ex_handler,  (p16)	ld8	r32=[src0],8);		/* 1 */				\
+EK(.ex_handler,  (p16)	ld8	r36=[src1],8);						\
+		 (p17)	shrp	r35=r33,r34,shift;;	/* 1 */				\
+EX(.ex_handler,  (p6)	ld8	r22=[src1]);	/* common, prime for tail section */	\
+		 nop.m	0;								\
+		 (p16)	shrp	r38=r36,r37,shift;					\
+EX(.ex_handler,  (p17)	st8	[dst0]=r35,8);		/* 1 */				\
+EK(.ex_handler,  (p17)	st8	[dst1]=r39,8);						\
+		 br.ctop.dptk.few 1b;;							\
+		 (p7)	add	src1=-8,src1;	/* back out for <8 byte case */		\
+		 shrp	r21=r22,r38,shift;	/* speculative work */			\
+		 br.sptk.few .unaligned_src_tail /* branch out of jump table */		\
+		 ;;
+	.align 32
+.jump_table:
+	COPYU(8)	// unaligned cases
+.jmp1:
+	COPYU(16)
+	COPYU(24)
+	COPYU(32)
+	COPYU(40)
+	COPYU(48)
+	COPYU(56)
+
+#undef A
+#undef B
+#undef C
+#undef D
+END(memcpy)
+
+/*
+ * Due to lack of local tag support in gcc 2.x assembler, it is not clear which
+ * instruction failed in the bundle.  The exception algorithm is that we
+ * first figure out the faulting address, then detect if there is any
+ * progress made on the copy, if so, redo the copy from last known copied
+ * location up to the faulting address (exclusive). In the copy_from_user
+ * case, remaining byte in kernel buffer will be zeroed.
+ *
+ * Take copy_from_user as an example, in the code there are multiple loads
+ * in a bundle and those multiple loads could span over two pages, the
+ * faulting address is calculated as page_round_down(max(src0, src1)).
+ * This is based on knowledge that if we can access one byte in a page, we
+ * can access any byte in that page.
+ *
+ * predicate used in the exception handler:
+ * p6-p7: direction
+ * p10-p11: src faulting addr calculation
+ * p12-p13: dst faulting addr calculation
+ */
+
+#define A	r19
+#define B	r20
+#define C	r21
+#define D	r22
+#define F	r28
+
+#define memset_arg0	r32
+#define memset_arg2	r33
+
+#define saved_retval	loc0
+#define saved_rtlink	loc1
+#define saved_pfs_stack	loc2
+
+.ex_hndlr_s:
+	add	src0=8,src0
+	br.sptk .ex_handler
+	;;
+.ex_hndlr_d:
+	add	dst0=8,dst0
+	br.sptk .ex_handler
+	;;
+.ex_hndlr_lcpy_1:
+	mov	src1=src_pre_mem
+	mov	dst1=dst_pre_mem
+	cmp.gtu	p10,p11=src_pre_mem,saved_in1
+	cmp.gtu	p12,p13=dst_pre_mem,saved_in0
+	;;
+(p10)	add	src0=8,saved_in1
+(p11)	mov	src0=saved_in1
+(p12)	add	dst0=8,saved_in0
+(p13)	mov	dst0=saved_in0
+	br.sptk	.ex_handler
+.ex_handler_lcpy:
+	// in line_copy block, the preload addresses should always ahead
+	// of the other two src/dst pointers.  Furthermore, src1/dst1 should
+	// always ahead of src0/dst0.
+	mov	src1=src_pre_mem
+	mov	dst1=dst_pre_mem
+.ex_handler:
+	mov	pr=saved_pr,-1		// first restore pr, lc, and pfs
+	mov	ar.lc=saved_lc
+	mov	ar.pfs=saved_pfs
+	;;
+.ex_handler_short: // fault occurred in these sections didn't change pr, lc, pfs
+	cmp.ltu	p6,p7=saved_in0, saved_in1	// get the copy direction
+	cmp.ltu	p10,p11=src0,src1
+	cmp.ltu	p12,p13=dst0,dst1
+	fcmp.eq	p8,p0=f6,f0		// is it memcpy?
+	mov	tmp = dst0
+	;;
+(p11)	mov	src1 = src0		// pick the larger of the two
+(p13)	mov	dst0 = dst1		// make dst0 the smaller one
+(p13)	mov	dst1 = tmp		// and dst1 the larger one
+	;;
+(p6)	dep	F = r0,dst1,0,PAGE_SHIFT // usr dst round down to page boundary
+(p7)	dep	F = r0,src1,0,PAGE_SHIFT // usr src round down to page boundary
+	;;
+(p6)	cmp.le	p14,p0=dst0,saved_in0	// no progress has been made on store
+(p7)	cmp.le	p14,p0=src0,saved_in1	// no progress has been made on load
+	mov	retval=saved_in2
+(p8)	ld1	tmp=[src1]		// force an oops for memcpy call
+(p8)	st1	[dst1]=r0		// force an oops for memcpy call
+(p14)	br.ret.sptk.many rp
+
+/*
+ * The remaining byte to copy is calculated as:
+ *
+ * A =	(faulting_addr - orig_src)	-> len to faulting ld address
+ *	or 
+ * 	(faulting_addr - orig_dst)	-> len to faulting st address
+ * B =	(cur_dst - orig_dst)		-> len copied so far
+ * C =	A - B				-> len need to be copied
+ * D =	orig_len - A			-> len need to be zeroed
+ */
+(p6)	sub	A = F, saved_in0
+(p7)	sub	A = F, saved_in1
+	clrrrb
+	;;
+	alloc	saved_pfs_stack=ar.pfs,3,3,3,0
+	sub	B = dst0, saved_in0	// how many byte copied so far
+	;;
+	sub	C = A, B
+	sub	D = saved_in2, A
+	;;
+	cmp.gt	p8,p0=C,r0		// more than 1 byte?
+	add	memset_arg0=saved_in0, A
+(p6)	mov	memset_arg2=0		// copy_to_user should not call memset
+(p7)	mov	memset_arg2=D		// copy_from_user need to have kbuf zeroed
+	mov	r8=0
+	mov	saved_retval = D
+	mov	saved_rtlink = b0
+
+	add	out0=saved_in0, B
+	add	out1=saved_in1, B
+	mov	out2=C
+(p8)	br.call.sptk.few b0=__copy_user	// recursive call
+	;;
+
+	add	saved_retval=saved_retval,r8	// above might return non-zero value
+	cmp.gt	p8,p0=memset_arg2,r0	// more than 1 byte?
+	mov	out0=memset_arg0	// *s
+	mov	out1=r0			// c
+	mov	out2=memset_arg2	// n
+(p8)	br.call.sptk.few b0=memset
+	;;
+
+	mov	retval=saved_retval
+	mov	ar.pfs=saved_pfs_stack
+	mov	b0=saved_rtlink
+	br.ret.sptk.many rp
+
+/* end of McKinley specific optimization */
+END(__copy_user)
diff -Nru a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c
--- a/arch/ia64/lib/swiotlb.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/lib/swiotlb.c	Thu Aug  1 01:08:13 2002
@@ -415,18 +415,21 @@
 swiotlb_map_sg (struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
 {
 	void *addr;
+	unsigned long pci_addr;
 	int i;
 
 	if (direction == PCI_DMA_NONE)
 		BUG();
 
 	for (i = 0; i < nelems; i++, sg++) {
-		sg->orig_address = SG_ENT_VIRT_ADDRESS(sg);
-		if ((SG_ENT_PHYS_ADDRESS(sg) & ~hwdev->dma_mask) != 0) {
-			addr = map_single(hwdev, sg->orig_address, sg->length, direction);
-			sg->page = virt_to_page(addr);
-			sg->offset = (u64) addr & ~PAGE_MASK;
-		}
+		addr = SG_ENT_VIRT_ADDRESS(sg);
+		pci_addr = virt_to_phys(addr);
+		if ((pci_addr & ~hwdev->dma_mask) != 0)
+			sg->dma_address = (dma_addr_t)
+				map_single(hwdev, addr, sg->length, direction);
+		else
+			sg->dma_address = pci_addr;
+		sg->dma_length = sg->length;
 	}
 	return nelems;
 }
@@ -444,12 +447,10 @@
 		BUG();
 
 	for (i = 0; i < nelems; i++, sg++)
-		if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg)) {
-			unmap_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction);
-			sg->page = virt_to_page(sg->orig_address);
-			sg->offset = (u64) sg->orig_address & ~PAGE_MASK;
-		} else if (direction == PCI_DMA_FROMDEVICE)
-			mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->length);
+		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
+			unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction);
+		else if (direction == PCI_DMA_FROMDEVICE)
+			mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
 }
 
 /*
@@ -468,14 +469,14 @@
 		BUG();
 
 	for (i = 0; i < nelems; i++, sg++)
-		if (sg->orig_address != SG_ENT_VIRT_ADDRESS(sg))
-			sync_single(hwdev, SG_ENT_VIRT_ADDRESS(sg), sg->length, direction);
+		if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
+			sync_single(hwdev, (void *) sg->dma_address, sg->dma_length, direction);
 }
 
 unsigned long
 swiotlb_dma_address (struct scatterlist *sg)
 {
-	return SG_ENT_PHYS_ADDRESS(sg);
+	return sg->dma_address;
 }
 
 /*
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/mm/init.c	Thu Aug  1 01:08:13 2002
@@ -10,6 +10,7 @@
 
 #include <linux/bootmem.h>
 #include <linux/mm.h>
+#include <linux/personality.h>
 #include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
@@ -68,10 +69,9 @@
 	struct vm_area_struct *vma;
 
 	/*
-	 * If we're out of memory and kmem_cache_alloc() returns NULL,
-	 * we simply ignore the problem.  When the process attempts to
-	 * write to the register backing store for the first time, it
-	 * will get a SEGFAULT in this case.
+	 * If we're out of memory and kmem_cache_alloc() returns NULL, we simply ignore
+	 * the problem.  When the process attempts to write to the register backing store
+	 * for the first time, it will get a SEGFAULT in this case.
 	 */
 	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
 	if (vma) {
@@ -86,6 +86,19 @@
 		vma->vm_private_data = NULL;
 		insert_vm_struct(current->mm, vma);
 	}
+
+	/* map NaT-page at address zero to speed up speculative dereferencing of NULL: */
+	if (!(current->personality & MMAP_PAGE_ZERO)) {
+		vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+		if (vma) {
+			memset(vma, 0, sizeof(*vma));
+			vma->vm_mm = current->mm;
+			vma->vm_end = PAGE_SIZE;
+			vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
+			vma->vm_flags = VM_READ | VM_MAYREAD | VM_IO | VM_RESERVED;
+			insert_vm_struct(current->mm, vma);
+		}
+	}
 }
 
 void
@@ -167,10 +180,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 +197,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/mm/tlb.c b/arch/ia64/mm/tlb.c
--- a/arch/ia64/mm/tlb.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/mm/tlb.c	Thu Aug  1 01:08:13 2002
@@ -35,12 +35,14 @@
 		1 << _PAGE_SIZE_4K )
 
 struct ia64_ctx ia64_ctx = {
-	lock:	SPIN_LOCK_UNLOCKED,
-	next:	1,
-	limit:	(1 << 15) - 1,		/* start out with the safe (architected) limit */
-	max_ctx: ~0U
+	.lock =		SPIN_LOCK_UNLOCKED,
+	.next =		1,
+	.limit =	(1 << 15) - 1,		/* start out with the safe (architected) limit */
+	.max_ctx =	~0U
 };
 
+u8 ia64_need_tlb_flush __per_cpu_data;
+
 /*
  * Acquire the ia64_ctx.lock before calling this function!
  */
@@ -49,6 +51,7 @@
 {
 	unsigned long tsk_context, max_ctx = ia64_ctx.max_ctx;
 	struct task_struct *tsk;
+	int i;
 
 	if (ia64_ctx.next > max_ctx)
 		ia64_ctx.next = 300;	/* skip daemons */
@@ -77,7 +80,11 @@
 			ia64_ctx.limit = tsk_context;
 	}
 	read_unlock(&tasklist_lock);
-	flush_tlb_all();
+	/* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */
+	for (i = 0; i < NR_CPUS; ++i)
+		if (i != smp_processor_id())
+			per_cpu(ia64_need_tlb_flush, i) = 1;
+	__flush_tlb_all();
 }
 
 void
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 01:08:12 2002
+++ b/arch/ia64/sn/io/hcl.c	Thu Aug  1 01:08:12 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/ia64/sn/io/ifconfig_net.c b/arch/ia64/sn/io/ifconfig_net.c
--- a/arch/ia64/sn/io/ifconfig_net.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/sn/io/ifconfig_net.c	Thu Aug  1 01:08:12 2002
@@ -279,9 +279,9 @@
 }
 
 struct file_operations ifconfig_net_fops = {
-	ioctl:ifconfig_net_ioctl,	/* ioctl */
-	open:ifconfig_net_open,		/* open */
-	release:ifconfig_net_close	/* release */
+	.ioctl =ifconfig_net_ioctl,	/* ioctl */
+	.open =ifconfig_net_open,		/* open */
+	.release =ifconfig_net_close	/* release */
 };
 
 
diff -Nru a/arch/ia64/sn/io/pciba.c b/arch/ia64/sn/io/pciba.c
--- a/arch/ia64/sn/io/pciba.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/sn/io/pciba.c	Thu Aug  1 01:08:12 2002
@@ -210,31 +210,31 @@
 
 /* file operations for each type of node */
 static struct file_operations rom_fops = {
-	owner:		THIS_MODULE,
-	mmap:		rom_mmap,
-	open:		generic_open,
-	release:	rom_release
+	.owner =	THIS_MODULE,
+	.mmap =		rom_mmap,
+	.open =		generic_open,
+	.release =	rom_release
 };
  
 
 static struct file_operations base_fops = {
-	owner:		THIS_MODULE,
-	mmap:		base_mmap,
-	open:		generic_open
+	.owner =	THIS_MODULE,
+	.mmap =		base_mmap,
+	.open =		generic_open
 };
 
 
 static struct file_operations config_fops = {
-	owner:		THIS_MODULE,
-	ioctl:		config_ioctl,
-	open:		generic_open
+	.owner =	THIS_MODULE,
+	.ioctl =	config_ioctl,
+	.open =		generic_open
 };	
 
 static struct file_operations dma_fops = {
-	owner:		THIS_MODULE,
-	ioctl:		dma_ioctl,
-	mmap:		dma_mmap,
-	open:		generic_open
+	.owner =	THIS_MODULE,
+	.ioctl =	dma_ioctl,
+	.mmap =		dma_mmap,
+	.open =		generic_open
 };	
 
 
diff -Nru a/arch/ia64/sn/io/sn1/hubcounters.c b/arch/ia64/sn/io/sn1/hubcounters.c
--- a/arch/ia64/sn/io/sn1/hubcounters.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/sn/io/sn1/hubcounters.c	Thu Aug  1 01:08:12 2002
@@ -24,7 +24,7 @@
 
 static int hubstats_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
 struct file_operations hub_mon_fops = {
-        ioctl:          hubstats_ioctl,
+        .ioctl =        hubstats_ioctl,
 };
 
 #define HUB_CAPTURE_TICKS	(2 * HZ)
diff -Nru a/arch/ia64/sn/io/sn1/pcibr.c b/arch/ia64/sn/io/sn1/pcibr.c
--- a/arch/ia64/sn/io/sn1/pcibr.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/sn/io/sn1/pcibr.c	Thu Aug  1 01:08:13 2002
@@ -307,22 +307,22 @@
  * appropriate function name below.
  */
 struct file_operations pcibr_fops = {
-        owner:  THIS_MODULE,
-        llseek: NULL,
-        read: NULL,
-        write: NULL,
-        readdir: NULL,
-        poll: NULL,
-        ioctl: NULL,
-        mmap: NULL,
-        open: NULL,
-        flush: NULL,
-        release: NULL,
-        fsync: NULL,
-        fasync: NULL,
-        lock: NULL,
-        readv: NULL,
-        writev: NULL
+        .owner = THIS_MODULE,
+        .llseek = NULL,
+        .read = NULL,
+        .write = NULL,
+        .readdir = NULL,
+        .poll = NULL,
+        .ioctl = NULL,
+        .mmap = NULL,
+        .open = NULL,
+        .flush = NULL,
+        .release = NULL,
+        .fsync = NULL,
+        .fasync = NULL,
+        .lock = NULL,
+        .readv = NULL,
+        .writev = NULL
 };
 
 extern devfs_handle_t hwgraph_root;
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
--- a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	Thu Aug  1 01:08:13 2002
+++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	Thu Aug  1 01:08:13 2002
@@ -64,22 +64,22 @@
  * appropriate function name below.
  */
 struct file_operations pcibr_fops = {
-	owner:  THIS_MODULE,
-	llseek: NULL,
-	read: NULL,
-	write: NULL,
-	readdir: NULL,
-	poll: NULL,
-	ioctl: NULL,
-	mmap: NULL,
-	open: NULL,
-	flush: NULL,
-	release: NULL,
-	fsync: NULL,
-	fasync: NULL,
-	lock: NULL,
-	readv: NULL,
-	writev: NULL
+	.owner =THIS_MODULE,
+	.llseek = NULL,
+	.read = NULL,
+	.write = NULL,
+	.readdir = NULL,
+	.poll = NULL,
+	.ioctl = NULL,
+	.mmap = NULL,
+	.open = NULL,
+	.flush = NULL,
+	.release = NULL,
+	.fsync = NULL,
+	.fasync = NULL,
+	.lock = NULL,
+	.readv = NULL,
+	.writev = NULL
 };
 
 #ifdef LATER
diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
--- a/arch/ia64/sn/kernel/setup.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/sn/kernel/setup.c	Thu Aug  1 01:08:12 2002
@@ -109,14 +109,14 @@
  * VGA color display.
  */
 struct screen_info sn1_screen_info = {
-	orig_x:			 0,
-	orig_y:			 0,
-	orig_video_mode:	 3,
-	orig_video_cols:	80,
-	orig_video_ega_bx:	 3,
-	orig_video_lines:	25,
-	orig_video_isVGA:	 1,
-	orig_video_points:	16
+	.orig_x =		 0,
+	.orig_y =		 0,
+	.orig_video_mode =	 3,
+	.orig_video_cols =	80,
+	.orig_video_ega_bx =	 3,
+	.orig_video_lines =	25,
+	.orig_video_isVGA =	 1,
+	.orig_video_points =	16
 };
 
 /*
@@ -170,9 +170,9 @@
 #ifdef NOT_YET_CONFIG_IA64_MCA
 extern void ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs);
 static struct irqaction mca_cpe_irqaction = { 
-	handler:    ia64_mca_cpe_int_handler,
-	flags:      SA_INTERRUPT,
-	name:       "cpe_hndlr"
+	.handler =  ia64_mca_cpe_int_handler,
+	.flags =    SA_INTERRUPT,
+	.name =     "cpe_hndlr"
 };
 #endif
 #ifdef CONFIG_IA64_MCA
diff -Nru a/arch/ia64/tools/Makefile b/arch/ia64/tools/Makefile
--- a/arch/ia64/tools/Makefile	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/tools/Makefile	Thu Aug  1 01:08:12 2002
@@ -4,7 +4,9 @@
 
 all:
 
-mrproper:
+fastdep:
+
+mrproper: clean
 
 clean:
 	rm -f print_offsets.s print_offsets offsets.h
diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S
--- a/arch/ia64/vmlinux.lds.S	Thu Aug  1 01:08:12 2002
+++ b/arch/ia64/vmlinux.lds.S	Thu Aug  1 01:08:12 2002
@@ -41,9 +41,6 @@
 
   /* Read-only data */
 
-  . = ALIGN(16);
-  __gp = . + 0x200000;	/* gp must be 16-byte aligned for exc. table */
-
   /* Global data */
   _data = .;
 
@@ -145,6 +142,9 @@
 
   .data : AT(ADDR(.data) - PAGE_OFFSET)
 	{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
+
+  . = ALIGN(16);
+  __gp = . + 0x200000;	/* gp must be 16-byte aligned for exc. table */
 
   .got : AT(ADDR(.got) - PAGE_OFFSET)
 	{ *(.got.plt) *(.got) }
diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c
--- a/arch/mips/mm/init.c	Thu Aug  1 01:08:13 2002
+++ b/arch/mips/mm/init.c	Thu Aug  1 01:08:13 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/mm/init.c b/arch/mips64/mm/init.c
--- a/arch/mips64/mm/init.c	Thu Aug  1 01:08:12 2002
+++ b/arch/mips64/mm/init.c	Thu Aug  1 01:08:12 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/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
--- a/arch/parisc/kernel/traps.c	Thu Aug  1 01:08:13 2002
+++ b/arch/parisc/kernel/traps.c	Thu Aug  1 01:08:13 2002
@@ -43,7 +43,6 @@
 
 static inline void console_verbose(void)
 {
-	extern int console_loglevel;
 	console_loglevel = 15;
 }
 
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 01:08:13 2002
+++ b/arch/ppc/boot/common/misc-common.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/ppc/boot/prep/Makefile	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/boot/prep/misc.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/ppc/boot/simple/Makefile	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/ppc/boot/simple/misc-spruce.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/config.in	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/ppc/kernel/Makefile	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/kernel/irq.c	Thu Aug  1 01:08:12 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/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	Thu Aug  1 01:08:12 2002
+++ b/arch/ppc/kernel/ppc_htab.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/ppc/kernel/ppc_ksyms.c	Thu Aug  1 01:08:13 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 01:08:13 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 01:08:13 2002
+++ b/arch/ppc/kernel/process.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/kernel/temp.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/ppc/kernel/time.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/ppc/mm/fault.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/ppc/mm/mmu_decl.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/mm/pgtable.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/ppc/mm/ppc_mmu.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/ppc/mm/tlb.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/ppc/platforms/Makefile	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/platforms/cpc700.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/arch/ppc/platforms/cpc700_pic.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/arch/ppc/platforms/iSeries_pic.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/arch/ppc/platforms/iSeries_time.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/platforms/lopec_setup.c	Thu Aug  1 01:08:12 2002
@@ -33,8 +33,15 @@
 #include <asm/bootinfo.h>
 #include <asm/mpc10x.h>
 #include <asm/hw_irq.h>
+#include <asm/prep_nvram.h>
+#include <asm/keyboard.h>
 
+extern char saved_command_line[];
 extern void lopec_find_bridges(void);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern unsigned char pckbd_sysrq_xlate[128];
 
 /*
  * Define all of the IRQ senses and polarities.  Taken from the
@@ -333,6 +340,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
 }
 
 void __init
@@ -362,6 +384,14 @@
 	ppc_md.find_end_of_memory = lopec_find_end_of_memory;
 	ppc_md.setup_io_mappings = lopec_map_io;
 
+#ifdef CONFIG_VT
+	ppc_md.kbd_translate = pckbd_translate;
+	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+#endif /* CONFIG_MAGIC_SYSRQ */
+#endif /* CONFIG_VT */
+ 
 	ppc_md.time_init = todc_time_init;
 	ppc_md.set_rtc_time = todc_set_rtc_time;
 	ppc_md.get_rtc_time = todc_get_rtc_time;
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 01:08:13 2002
+++ b/arch/ppc/platforms/pplus_setup.c	Thu Aug  1 01:08:13 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 01:08:13 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 01:08:12 2002
+++ b/arch/ppc/platforms/spruce_setup.c	Thu Aug  1 01:08:12 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/sparc/mm/init.c b/arch/sparc/mm/init.c
--- a/arch/sparc/mm/init.c	Thu Aug  1 01:08:13 2002
+++ b/arch/sparc/mm/init.c	Thu Aug  1 01:08:13 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/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	Thu Aug  1 01:08:13 2002
+++ b/arch/sparc64/mm/init.c	Thu Aug  1 01:08:13 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/drivers/acpi/bus.c b/drivers/acpi/bus.c
--- a/drivers/acpi/bus.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/acpi/bus.c	Thu Aug  1 01:08:13 2002
@@ -2167,6 +2167,6 @@
 	return 1;
 }
 
-subsys_initcall(acpi_init);
+arch_initcall(acpi_init); /* XXX fix me: should be subsys_initcall */
 
 __setup("acpi=", acpi_setup);
diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c
--- a/drivers/acpi/osl.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/acpi/osl.c	Thu Aug  1 01:08:13 2002
@@ -80,6 +80,7 @@
 	 * it while walking the namespace (bus 0 and root bridges w/ _BBNs).
 	 */
 #ifdef CONFIG_ACPI_PCI
+	pcibios_config_init();
 	if (!pci_config_read || !pci_config_write) {
 		printk(KERN_ERR PREFIX "Access to PCI configuration space unavailable\n");
 		return AE_NULL_ENTRY;
@@ -176,10 +177,10 @@
 acpi_os_map_memory(ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size, void **virt)
 {
 #ifdef CONFIG_ACPI_EFI
-	if (!(EFI_MEMORY_WB & efi_mem_attributes(phys))) {
-		*virt = ioremap(phys, size);
-	} else {
+	if (EFI_MEMORY_WB & efi_mem_attributes(phys)) {
 		*virt = phys_to_virt(phys);
+	} else {
+		*virt = ioremap(phys, size);
 	}
 #else
 	if (phys > ULONG_MAX) {
@@ -351,8 +352,7 @@
 
 	if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
 		virt_addr = phys_to_virt(phys_addr);
-	}
-	else {
+	} else {
 		iomem = 1;
 		virt_addr = ioremap(phys_addr, width);
 	}
@@ -397,8 +397,7 @@
 
 	if (EFI_MEMORY_WB & efi_mem_attributes(phys_addr)) {
 		virt_addr = phys_to_virt(phys_addr);
-	}
-	else {
+	} else {
 		iomem = 1;
 		virt_addr = ioremap(phys_addr, width);
 	}
diff -Nru a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
--- a/drivers/acpi/pci_irq.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/acpi/pci_irq.c	Thu Aug  1 01:08:13 2002
@@ -33,7 +33,9 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/acpi.h>
+#ifdef CONFIG_X86_IO_APIC
 #include <asm/mpspec.h>
+#endif
 #include "acpi_bus.h"
 #include "acpi_drivers.h"
 
diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
--- a/drivers/block/cpqarray.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/block/cpqarray.c	Thu Aug  1 01:08:12 2002
@@ -336,7 +336,7 @@
 
 		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);
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 01:08:12 2002
+++ b/drivers/block/ll_rw_blk.c	Thu Aug  1 01:08:12 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);
diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c
--- a/drivers/block/rd.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/block/rd.c	Thu Aug  1 01:08:13 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/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
--- a/drivers/cdrom/aztcd.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/cdrom/aztcd.c	Thu Aug  1 01:08:13 2002
@@ -1957,8 +1957,7 @@
 
 void __exit aztcd_exit(void)
 {
-	devfs_unregister(devfs_find_handle
-			 (NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0));
+	devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
 	if ((devfs_unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
 		printk("What's that: can't unregister aztcd\n");
 		return;
diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
--- a/drivers/cdrom/gscd.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/cdrom/gscd.c	Thu Aug  1 01:08:12 2002
@@ -933,8 +933,7 @@
 {
 	CLEAR_TIMER;
 
-	devfs_unregister(devfs_find_handle
-			 (NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0));
+	devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0);
 	if ((devfs_unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
 		printk("What's that: can't unregister GoldStar-module\n");
 		return;
diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
--- a/drivers/cdrom/optcd.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/cdrom/optcd.c	Thu Aug  1 01:08:12 2002
@@ -2051,8 +2051,7 @@
 
 void __exit optcd_exit(void)
 {
-	devfs_unregister(devfs_find_handle(NULL, "optcd", 0, 0,
-					   DEVFS_SPECIAL_BLK, 0));
+	devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
 	if (devfs_unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
 		printk(KERN_ERR "optcd: what's that: can't unregister\n");
 		return;
diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
--- a/drivers/cdrom/sjcd.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/cdrom/sjcd.c	Thu Aug  1 01:08:13 2002
@@ -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 01:08:13 2002
+++ b/drivers/cdrom/sonycd535.c	Thu Aug  1 01:08:13 2002
@@ -1700,8 +1700,8 @@
 	kfree(sony_buffer);
 	kfree(last_sony_subcode);
 	kfree(sony_toc);
-	devfs_unregister(devfs_find_handle(NULL, CDU535_HANDLE, 0, 0,
-					   DEVFS_SPECIAL_BLK, 0));
+	devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0,
+				  DEVFS_SPECIAL_BLK, 0);
 	if (devfs_unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
 		printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
 	else
diff -Nru a/drivers/char/Config.help b/drivers/char/Config.help
--- a/drivers/char/Config.help	Thu Aug  1 01:08:13 2002
+++ b/drivers/char/Config.help	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/drivers/char/Config.in	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/drivers/char/Makefile	Thu Aug  1 01:08:13 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/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
--- a/drivers/char/ftape/zftape/zftape-init.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/char/ftape/zftape/zftape-init.c	Thu Aug  1 01:08:13 2002
@@ -426,17 +426,17 @@
 	}
         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/mem.c b/drivers/char/mem.c
--- a/drivers/char/mem.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/char/mem.c	Thu Aug  1 01:08:13 2002
@@ -518,6 +518,7 @@
 		default:
 			ret = -EINVAL;
 	}
+	force_successful_syscall_return();
 	unlock_kernel();
 	return ret;
 }
diff -Nru a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
--- a/drivers/char/n_r3964.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/char/n_r3964.c	Thu Aug  1 01:08:13 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/raw.c b/drivers/char/raw.c
--- a/drivers/char/raw.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/char/raw.c	Thu Aug  1 01:08:12 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/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/char/tpqic02.c	Thu Aug  1 01:08:13 2002
@@ -2931,30 +2931,22 @@
 		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));
+	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 01:08:13 2002
+++ b/drivers/char/tty_io.c	Thu Aug  1 01:08:13 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 */
 }
 
diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
--- a/drivers/char/vc_screen.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/char/vc_screen.c	Thu Aug  1 01:08:12 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
     {
diff -Nru a/drivers/ide/cmd640.c b/drivers/ide/cmd640.c
--- a/drivers/ide/cmd640.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/ide/cmd640.c	Thu Aug  1 01:08:13 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/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
--- a/drivers/isdn/capi/capi.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/isdn/capi/capi.c	Thu Aug  1 01:08:13 2002
@@ -1527,7 +1527,7 @@
 	proc_exit();
 
 	devfs_unregister_chrdev(capi_major, "capi20");
-	devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0));
+	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/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/md/md.c	Thu Aug  1 01:08:12 2002
@@ -3412,12 +3412,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);
diff -Nru a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
--- a/drivers/media/radio/Makefile	Thu Aug  1 01:08:12 2002
+++ b/drivers/media/radio/Makefile	Thu Aug  1 01:08:12 2002
@@ -5,6 +5,8 @@
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
+obj-y		:= dummy.o
+
 export-objs     := miropcm20-rds-core.o
 
 miropcm20-objs	:= miropcm20-rds-core.o miropcm20-radio.o
diff -Nru a/drivers/media/radio/dummy.c b/drivers/media/radio/dummy.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/radio/dummy.c	Thu Aug  1 01:08:13 2002
@@ -0,0 +1 @@
+/* just so the linker knows what kind of object files it's deadling with... */
diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile
--- a/drivers/media/video/Makefile	Thu Aug  1 01:08:13 2002
+++ b/drivers/media/video/Makefile	Thu Aug  1 01:08:13 2002
@@ -5,7 +5,8 @@
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
 
-export-objs     :=	videodev.o bttv-if.o cpia.o video-buf.o
+obj-y		:= dummy.o
+
 
 bttv-objs	:=	bttv-driver.o bttv-cards.o bttv-if.o \
 			bttv-risc.o bttv-vbi.o
diff -Nru a/drivers/media/video/dummy.c b/drivers/media/video/dummy.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/media/video/dummy.c	Thu Aug  1 01:08:13 2002
@@ -0,0 +1 @@
+/* just so the linker knows what kind of object files it's deadling with... */
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/message/fusion/mptscsih.c	Thu Aug  1 01:08:13 2002
@@ -99,6 +99,8 @@
 MODULE_PARM(mptscsih, "s");
 #endif
 
+static spinlock_t detect_lock = SPIN_LOCK_UNLOCKED;
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 typedef struct _BIG_SENSE_BUF {
@@ -1156,8 +1158,7 @@
 #endif
 			sh = scsi_register(tpnt, sizeof(MPT_SCSI_HOST));
 			if (sh != NULL) {
-				save_flags(flags);
-				cli();
+				spin_lock_irqsave(&detect_lock, flags);
 				sh->io_port = 0;
 				sh->n_io_port = 0;
 				sh->irq = 0;
@@ -1221,7 +1222,7 @@
 				 */
 				scsi_set_pci_device(sh, this->pcidev);
 
-				restore_flags(flags);
+				spin_unlock_irqrestore(&detect_lock, flags);
 
 				hd = (MPT_SCSI_HOST *) sh->hostdata;
 				hd->ioc = this;
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 01:08:13 2002
+++ b/drivers/net/e1000/e1000_main.c	Thu Aug  1 01:08:13 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/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/net/eepro100.c	Thu Aug  1 01:08:13 2002
@@ -25,6 +25,8 @@
 		Disabled FC and ER, to avoid lockups when when we get FCP interrupts.
 	2000 Jul 17 Goutham Rao <goutham.rao@intel.com>
 		PCI DMA API fixes, adding pci_dma_sync_single calls where neccesary
+    2000 Aug 31 David Mosberger <davidm@hpl.hp.com>
+	    RX_ALIGN support: enables rx DMA without causing unaligned accesses.
 */
 
 static const char *version =
@@ -41,14 +43,18 @@
 static int txdmacount = 128;
 static int rxdmacount /* = 0 */;
 
+#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
+	defined(__arm__)
+  /* align rx buffers to 2 bytes so that IP header is aligned */
+# define RX_ALIGN
+# define RxFD_ALIGNMENT		__attribute__ ((aligned (2), packed))
+#else
+# define RxFD_ALIGNMENT
+#endif
+
 /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
    Lower values use more memory, but are faster. */
-#if defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
-    defined(__arm__)
-static int rx_copybreak = 1518;
-#else
 static int rx_copybreak = 200;
-#endif
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 20;
@@ -377,18 +383,18 @@
 
 /* The Speedo3 Rx and Tx frame/buffer descriptors. */
 struct descriptor {			    /* A generic descriptor. */
-	s32 cmd_status;				/* All command and status fields. */
+	volatile s32 cmd_status;	/* All command and status fields. */
 	u32 link;				    /* struct descriptor *  */
 	unsigned char params[0];
 };
 
 /* The Speedo3 Rx and Tx buffer descriptors. */
 struct RxFD {					/* Receive frame descriptor. */
-	s32 status;
+	volatile s32 status;
 	u32 link;					/* struct RxFD * */
 	u32 rx_buf_addr;			/* void * */
 	u32 count;
-};
+} RxFD_ALIGNMENT;
 
 /* Selected elements of the Tx/RxFD.status word. */
 enum RxFD_bits {
@@ -523,7 +529,12 @@
 
 static int eepro100_init_one(struct pci_dev *pdev,
 		const struct pci_device_id *ent);
+
 static void eepro100_remove_one (struct pci_dev *pdev);
+#ifdef CONFIG_PM
+static int eepro100_suspend (struct pci_dev *pdev, u32 state);
+static int eepro100_resume (struct pci_dev *pdev);
+#endif
 
 static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);
 static int mdio_read(long ioaddr, int phy_id, int location);
@@ -1229,6 +1240,9 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		struct sk_buff *skb;
 		skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
+#ifdef RX_ALIGN
+		skb_reserve(skb, 2);	/* Align IP on 16 byte boundary */
+#endif
 		sp->rx_skbuff[i] = skb;
 		if (skb == NULL)
 			break;			/* OK.  Just initially short of Rx bufs. */
@@ -1620,6 +1634,9 @@
 	struct sk_buff *skb;
 	/* Get a fresh skbuff to replace the consumed one. */
 	skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
+#ifdef RX_ALIGN
+	skb_reserve(skb, 2);	/* Align IP on 16 byte boundary */
+#endif
 	sp->rx_skbuff[entry] = skb;
 	if (skb == NULL) {
 		sp->rx_ringp[entry] = NULL;
@@ -2303,7 +2320,9 @@
 	name:		"eepro100",
 	id_table:	eepro100_pci_tbl,
 	probe:		eepro100_init_one,
+# if defined(MODULE) || defined(CONFIG_HOTPLUG)
 	remove:		__devexit_p(eepro100_remove_one),
+# endif
 #ifdef CONFIG_PM
 	suspend:	eepro100_suspend,
 	resume:		eepro100_resume,
diff -Nru a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
--- a/drivers/net/tulip/media.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/net/tulip/media.c	Thu Aug  1 01:08:12 2002
@@ -278,6 +278,10 @@
 				for (i = 0; i < init_length; i++)
 					outl(init_sequence[i], ioaddr + CSR12);
 			}
+
+			(void) inl(ioaddr + CSR6); /* flush CSR12 writes */
+			udelay(500);		/* Give MII time to recover */
+
 			tmp_info = get_u16(&misc_info[1]);
 			if (tmp_info)
 				tp->advertising[phy_num] = tmp_info | 1;
diff -Nru a/drivers/parport/share.c b/drivers/parport/share.c
--- a/drivers/parport/share.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/parport/share.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/drivers/pci/access.c	Thu Aug  1 01:08:13 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/pnp/pnpbios_core.c b/drivers/pnp/pnpbios_core.c
--- a/drivers/pnp/pnpbios_core.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/pnp/pnpbios_core.c	Thu Aug  1 01:08:12 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/char/tubfs.c b/drivers/s390/char/tubfs.c
--- a/drivers/s390/char/tubfs.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/s390/char/tubfs.c	Thu Aug  1 01:08:13 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
 
diff -Nru a/drivers/sbus/audio/audio.c b/drivers/sbus/audio/audio.c
--- a/drivers/sbus/audio/audio.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/sbus/audio/audio.c	Thu Aug  1 01:08:12 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;
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/scsi/megaraid.c	Thu Aug  1 01:08:12 2002
@@ -2036,9 +2036,6 @@
 
 
 #if DEBUG
-static unsigned int cum_time = 0;
-static unsigned int cum_time_cnt = 0;
-
 static void showMbox (mega_scb * pScb)
 {
 	mega_mailbox *mbox;
@@ -2047,7 +2044,7 @@
 		return;
 
 	mbox = (mega_mailbox *) pScb->mboxData;
-	printk ("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",
+	printk ("%lu cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",
 		pScb->SCpnt->pid,
 		mbox->cmd, mbox->cmdid, mbox->numsectors,
 		mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements);
@@ -2293,7 +2290,7 @@
 #endif
 
 #if DEBUG
-	ShowMbox (pScb);
+       ShowMbox (pScb);
 #endif
 
 	/* Wait until mailbox is free */
@@ -3356,9 +3353,13 @@
 	mbox[0] = IS_BIOS_ENABLED;
 	mbox[2] = GET_BIOS;
 
-	mboxpnt->xferaddr = virt_to_bus ((void *) megacfg->mega_buffer);
+	mboxpnt->xferaddr = pci_map_single(megacfg->dev,
+				(void *) megacfg->mega_buffer, (2 * 1024L),
+				PCI_DMA_FROMDEVICE);
 
 	ret = megaIssueCmd (megacfg, mbox, NULL, 0);
+
+	pci_unmap_single(megacfg->dev, mboxpnt->xferaddr, 2 * 1024L, PCI_DMA_FROMDEVICE);
 
 	return (*(char *) megacfg->mega_buffer);
 }
diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c
--- a/drivers/scsi/scsi_ioctl.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/scsi/scsi_ioctl.c	Thu Aug  1 01:08:13 2002
@@ -196,6 +196,9 @@
 	unsigned int needed, buf_needed;
 	int timeout, retries, result;
 	int data_direction, gfp_mask = GFP_KERNEL;
+#if __GNUC__ < 3
+	int foo;
+#endif
 
 	if (!sic)
 		return -EINVAL;
@@ -209,11 +212,21 @@
 	if (verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)))
 		return -EFAULT;
 
+#if __GNUC__ < 3
+	foo = __get_user(inlen, &sic->inlen);
+	if (foo)
+		return -EFAULT;
+
+	foo = __get_user(outlen, &sic->outlen);
+	if (foo)
+		return -EFAULT;
+#else
 	if(__get_user(inlen, &sic->inlen))
 		return -EFAULT;
 		
 	if(__get_user(outlen, &sic->outlen))
 		return -EFAULT;
+#endif
 
 	/*
 	 * We do not transfer more than MAX_BUF with this interface.
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/scsi/scsi_scan.c	Thu Aug  1 01:08:13 2002
@@ -715,7 +715,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;
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/scsi/sd.c	Thu Aug  1 01:08:12 2002
@@ -1077,7 +1077,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;
 
diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c
--- a/drivers/serial/21285.c	Thu Aug  1 01:08:12 2002
+++ b/drivers/serial/21285.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/drivers/serial/8250.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/drivers/serial/8250_pci.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/drivers/serial/amba.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/drivers/serial/anakin.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/drivers/serial/clps711x.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/drivers/serial/core.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/drivers/serial/sa1100.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/drivers/serial/uart00.c	Thu Aug  1 01:08:13 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/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/usb/input/hiddev.c	Thu Aug  1 01:08:13 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/video/radeonfb.c b/drivers/video/radeonfb.c
--- a/drivers/video/radeonfb.c	Thu Aug  1 01:08:13 2002
+++ b/drivers/video/radeonfb.c	Thu Aug  1 01:08:13 2002
@@ -233,8 +233,8 @@
 	u32 mmio_base_phys;
 	u32 fb_base_phys;
 
-	u32 mmio_base;
-	u32 fb_base;
+	void *mmio_base;
+	void *fb_base;
 
 	struct pci_dev *pdev;
 
@@ -727,8 +727,7 @@
 	}
 
 	/* map the regions */
-	rinfo->mmio_base = (u32) ioremap (rinfo->mmio_base_phys,
-				    		    RADEON_REGSIZE);
+	rinfo->mmio_base = ioremap (rinfo->mmio_base_phys, RADEON_REGSIZE);
 	if (!rinfo->mmio_base) {
 		printk ("radeonfb: cannot map MMIO\n");
 		release_mem_region (rinfo->mmio_base_phys,
@@ -858,8 +857,7 @@
 		}
 	}
 
-	rinfo->fb_base = (u32) ioremap (rinfo->fb_base_phys,
-				  		  rinfo->video_ram);
+	rinfo->fb_base = ioremap (rinfo->fb_base_phys, rinfo->video_ram);
 	if (!rinfo->fb_base) {
 		printk ("radeonfb: cannot map FB\n");
 		iounmap ((void*)rinfo->mmio_base);
diff -Nru a/fs/adfs/file.c b/fs/adfs/file.c
--- a/fs/adfs/file.c	Thu Aug  1 01:08:12 2002
+++ b/fs/adfs/file.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/affs/file.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/bfs/file.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/binfmt_elf.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/block_dev.c	Thu Aug  1 01:08:13 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)
@@ -489,11 +505,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)
@@ -774,6 +791,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 01:08:12 2002
+++ b/fs/buffer.c	Thu Aug  1 01:08:12 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/sysctl.c b/fs/coda/sysctl.c
--- a/fs/coda/sysctl.c	Thu Aug  1 01:08:13 2002
+++ b/fs/coda/sysctl.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/devfs/base.c	Thu Aug  1 01:08:12 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  */
+}
 
 
 /**
@@ -2368,7 +2370,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);
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	Thu Aug  1 01:08:12 2002
+++ b/fs/direct-io.c	Thu Aug  1 01:08:12 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/exec.c b/fs/exec.c
--- a/fs/exec.c	Thu Aug  1 01:08:13 2002
+++ b/fs/exec.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/ext2/file.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/ext2/inode.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/ext3/dir.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/ext3/file.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/ext3/inode.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/ext3/namei.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/ext3/super.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/ext3/symlink.c	Thu Aug  1 01:08:13 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/fcntl.c b/fs/fcntl.c
--- a/fs/fcntl.c	Thu Aug  1 01:08:12 2002
+++ b/fs/fcntl.c	Thu Aug  1 01:08:12 2002
@@ -303,6 +303,7 @@
 			 * to fix this will be in libc.
 			 */
 			err = filp->f_owner.pid;
+			force_successful_syscall_return();
 			break;
 		case F_SETOWN:
 			lock_kernel();
diff -Nru a/fs/freevxfs/vxfs_inode.c b/fs/freevxfs/vxfs_inode.c
--- a/fs/freevxfs/vxfs_inode.c	Thu Aug  1 01:08:12 2002
+++ b/fs/freevxfs/vxfs_inode.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/hpfs/inode.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/intermezzo/sysctl.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs/inode-v23.c	Thu Aug  1 01:08:13 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 01:08:13 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 01:08:13 2002
+++ b/fs/jffs2/TODO	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/background.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/build.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/compr.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/compr_rtime.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/compr_rubin.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/compr_zlib.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/dir.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/erase.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/file.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/jffs2/fs.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/gc.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/ioctl.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/malloc.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/nodelist.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/jffs2/nodelist.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/nodemgmt.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/os-linux.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/pushpull.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/read.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/readinode.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/scan.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jffs2/super.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/symlink.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jffs2/wbuf.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jffs2/write.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/jffs2/writev.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/jfs/file.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/jfs/inode.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/jfs/namei.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/locks.c	Thu Aug  1 01:08:13 2002
@@ -1242,6 +1242,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 +1362,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 +1496,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 +1619,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;
 
diff -Nru a/fs/minix/file.c b/fs/minix/file.c
--- a/fs/minix/file.c	Thu Aug  1 01:08:13 2002
+++ b/fs/minix/file.c	Thu Aug  1 01:08:13 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/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	Thu Aug  1 01:08:13 2002
+++ b/fs/nfs/dir.c	Thu Aug  1 01:08:13 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,7 +198,6 @@
 
 	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,
 			       (filler_t *)nfs_readdir_filler, desc);
 	if (IS_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;
+	}
+
 	error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
-	inode = NULL;
 	if (error == -ENOENT)
 		goto no_entry;
 	if (!error) {
@@ -602,6 +658,79 @@
 	unlock_kernel();
 out:
 	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_data, 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 01:08:13 2002
+++ b/fs/nfs/inode.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/fs/nfs/nfs2xdr.c	Thu Aug  1 01:08:13 2002
@@ -118,6 +118,7 @@
 		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
 		fattr->rdev = 0;
 	}
+	fattr->timestamp = jiffies;
 	return p;
 }
 
diff -Nru a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
--- a/fs/nfs/nfs3xdr.c	Thu Aug  1 01:08:13 2002
+++ b/fs/nfs/nfs3xdr.c	Thu Aug  1 01:08:13 2002
@@ -181,6 +181,7 @@
 
 	/* Update the mode bits */
 	fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
+	fattr->timestamp = jiffies;
 	return p;
 }
 
@@ -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 01:08:12 2002
+++ b/fs/nfs/write.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/ntfs/file.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/partitions/Config.in	Thu Aug  1 01:08:12 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/msdos.c b/fs/partitions/msdos.c
--- a/fs/partitions/msdos.c	Thu Aug  1 01:08:12 2002
+++ b/fs/partitions/msdos.c	Thu Aug  1 01:08:12 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/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	Thu Aug  1 01:08:12 2002
+++ b/fs/proc/base.c	Thu Aug  1 01:08:12 2002
@@ -508,7 +508,24 @@
 }
 #endif
 
+static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
+{
+	switch (orig) {
+	      case 0:
+		file->f_pos = offset;
+		break;
+	      case 1:
+		file->f_pos += offset;
+		break;
+	      default:
+		return -EINVAL;
+	}
+	force_successful_syscall_return();
+	return file->f_pos;
+}
+
 static struct file_operations proc_mem_operations = {
+	llseek:		mem_lseek,
 	read:		mem_read,
 	write:		mem_write,
 	open:		mem_open,
diff -Nru a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
--- a/fs/proc/proc_misc.c	Thu Aug  1 01:08:12 2002
+++ b/fs/proc/proc_misc.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/qnx4/file.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/ramfs/inode.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/read_write.c	Thu Aug  1 01:08:13 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)
@@ -435,4 +436,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 01:08:12 2002
+++ b/fs/reiserfs/file.c	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/fs/smbfs/file.c	Thu Aug  1 01:08:13 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/sysv/file.c b/fs/sysv/file.c
--- a/fs/sysv/file.c	Thu Aug  1 01:08:13 2002
+++ b/fs/sysv/file.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/fs/udf/file.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/fs/ufs/file.c	Thu Aug  1 01:08:12 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/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 01:08:12 2002
+++ b/include/asm-arm/arch-ebsa285/keyboard.h	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/include/asm-arm/arch-integrator/keyboard.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/asm-arm/arch-rpc/keyboard.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/asm-arm/arch-sa1100/hardware.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/asm-arm/arch-sa1100/keyboard.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/asm-arm/atomic.h	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/include/asm-arm/hardirq.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/asm-arm/hardware/sa1111.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/asm-arm/io.h	Thu Aug  1 01:08:12 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 01:08:12 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 01:08:12 2002
+++ b/include/asm-arm/proc-armv/system.h	Thu Aug  1 01:08:12 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/rmap.h b/include/asm-arm/rmap.h
--- a/include/asm-arm/rmap.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-arm/rmap.h	Thu Aug  1 01:08:12 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/softirq.h b/include/asm-arm/softirq.h
--- a/include/asm-arm/softirq.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-arm/softirq.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/asm-arm/system.h	Thu Aug  1 01:08:12 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-i386/desc.h b/include/asm-i386/desc.h
--- a/include/asm-i386/desc.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-i386/desc.h	Thu Aug  1 01:08:12 2002
@@ -86,11 +86,10 @@
 	_set_tssldt_desc(&cpu_gdt_table[cpu][LDT_ENTRY], (int)addr, ((size << 3)-1), 0x82);
 }
 
-#define TLS_FLAGS_MASK			0x00000007
+#define TLS_FLAGS_MASK			0x00000003
 
-#define TLS_FLAG_LIMIT_IN_PAGES		0x00000001
-#define TLS_FLAG_WRITABLE		0x00000002
-#define TLS_FLAG_CLEAR			0x00000004
+#define TLS_FLAG_WRITABLE		0x00000001
+#define TLS_FLAG_CLEAR			0x00000002
 
 static inline void load_TLS_desc(struct thread_struct *t, unsigned int cpu)
 {
diff -Nru a/include/asm-i386/hw_irq.h b/include/asm-i386/hw_irq.h
--- a/include/asm-i386/hw_irq.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-i386/hw_irq.h	Thu Aug  1 01:08:13 2002
@@ -107,4 +107,6 @@
 static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {}
 #endif
 
+extern irq_desc_t irq_desc [NR_IRQS];
+
 #endif /* _ASM_HW_IRQ_H */
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-i386/processor.h	Thu Aug  1 01:08:12 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/ptrace.h b/include/asm-i386/ptrace.h
--- a/include/asm-i386/ptrace.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-i386/ptrace.h	Thu Aug  1 01:08:12 2002
@@ -58,6 +58,7 @@
 #define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
 #define instruction_pointer(regs) ((regs)->eip)
 extern void show_regs(struct pt_regs *);
+#define force_successful_syscall_return()	do { } while (0)
 #endif
 
 #endif
diff -Nru a/include/asm-i386/rwsem.h b/include/asm-i386/rwsem.h
--- a/include/asm-i386/rwsem.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-i386/rwsem.h	Thu Aug  1 01:08:13 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-ia64/acpi.h b/include/asm-ia64/acpi.h
--- a/include/asm-ia64/acpi.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/acpi.h	Thu Aug  1 01:08:12 2002
@@ -30,11 +30,74 @@
 
 #ifdef __KERNEL__
 
-#define __acpi_map_table(phys_addr, size) __va(phys_addr)
+#define COMPILER_DEPENDENT_INT64	long
+#define COMPILER_DEPENDENT_UINT64	unsigned long
+
+/*
+ * Calling conventions:
+ *
+ * ACPI_SYSTEM_XFACE        - Interfaces to host OS (handlers, threads)
+ * ACPI_EXTERNAL_XFACE      - External ACPI interfaces
+ * ACPI_INTERNAL_XFACE      - Internal ACPI interfaces
+ * ACPI_INTERNAL_VAR_XFACE  - Internal variable-parameter list interfaces
+ */
+#define ACPI_SYSTEM_XFACE
+#define ACPI_EXTERNAL_XFACE
+#define ACPI_INTERNAL_XFACE
+#define ACPI_INTERNAL_VAR_XFACE
+
+/* Asm macros */
+
+#define ACPI_ASM_MACROS
+#define BREAKPOINT3
+#define ACPI_DISABLE_IRQS() local_irq_disable()
+#define ACPI_ENABLE_IRQS()  local_irq_enable()
+#define ACPI_FLUSH_CPU_CACHE()
+
+#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) \
+	do { \
+	__asm__ volatile ("1:  ld4      r29=%1\n"  \
+		";;\n"                  \
+		"mov    ar.ccv=r29\n"   \
+		"mov    r2=r29\n"       \
+		"shr.u  r30=r29,1\n"    \
+		"and    r29=-4,r29\n"   \
+		";;\n"                  \
+		"add    r29=2,r29\n"    \
+		"and    r30=1,r30\n"    \
+		";;\n"                  \
+		"add    r29=r29,r30\n"  \
+		";;\n"                  \
+		"cmpxchg4.acq   r30=%1,r29,ar.ccv\n" \
+		";;\n"                  \
+		"cmp.eq p6,p7=r2,r30\n" \
+		"(p7) br.dpnt.few 1b\n" \
+		"cmp.gt p8,p9=3,r29\n"  \
+		";;\n"                  \
+		"(p8) mov %0=-1\n"      \
+		"(p9) mov %0=r0\n"      \
+		:"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \
+	} while (0)
+
+#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) \
+	do { \
+	__asm__ volatile ("1:  ld4      r29=%1\n" \
+		";;\n"                  \
+		"mov    ar.ccv=r29\n"   \
+		"mov    r2=r29\n"       \
+		"and    r29=-4,r29\n"   \
+		";;\n"                  \
+		"cmpxchg4.acq   r30=%1,r29,ar.ccv\n" \
+		";;\n"                  \
+		"cmp.eq p6,p7=r2,r30\n" \
+		"(p7) br.dpnt.few 1b\n" \
+		"and    %0=1,r2\n"      \
+		";;\n"                  \
+		:"=r"(Acq):"m"(GLptr):"r2","r29","r30","memory"); \
+	} while (0)
 
 const char *acpi_get_sysname (void);
 int acpi_boot_init (char *cdline);
-int acpi_find_rsdp (unsigned long *phys_addr);
 int acpi_request_vector (u32 int_type);
 int acpi_get_prt (struct pci_vector_struct **vectors, int *count);
 int acpi_get_interrupt_model(int *type);
diff -Nru a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
--- a/include/asm-ia64/bitops.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/bitops.h	Thu Aug  1 01:08:13 2002
@@ -326,7 +326,7 @@
 	return exp - 0xffff;
 }
 
-static int
+static inline int
 fls (int x)
 {
 	return ia64_fls((unsigned int) x);
diff -Nru a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h
--- a/include/asm-ia64/cacheflush.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/cacheflush.h	Thu Aug  1 01:08:12 2002
@@ -6,6 +6,8 @@
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
+#include <linux/page-flags.h>
+
 #include <asm/bitops.h>
 #include <asm/page.h>
 
@@ -23,7 +25,7 @@
 
 #define flush_dcache_page(page)			\
 do {						\
-	clear_bit(PG_arch_1, &page->flags);	\
+	clear_bit(PG_arch_1, &(page)->flags);	\
 } while (0)
 
 extern void flush_icache_range (unsigned long start, unsigned long end);
diff -Nru a/include/asm-ia64/delay.h b/include/asm-ia64/delay.h
--- a/include/asm-ia64/delay.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/delay.h	Thu Aug  1 01:08:12 2002
@@ -53,7 +53,7 @@
 
 	__asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
 #ifdef CONFIG_ITANIUM
-	while (unlikely ((__s32) result == -1)
+	while (unlikely((__s32) result == -1))
 		__asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
 #endif
 	return result;
diff -Nru a/include/asm-ia64/hardirq.h b/include/asm-ia64/hardirq.h
--- a/include/asm-ia64/hardirq.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/hardirq.h	Thu Aug  1 01:08:12 2002
@@ -18,88 +18,92 @@
  */
 #define softirq_pending(cpu)		(cpu_data(cpu)->softirq_pending)
 #define ksoftirqd_task(cpu)		(cpu_data(cpu)->ksoftirqd)
-#define irq_count(cpu)			(cpu_data(cpu)->irq_stat.f.irq_count)
-#define bh_count(cpu)			(cpu_data(cpu)->irq_stat.f.bh_count)
 #define syscall_count(cpu)		/* unused on IA-64 */
 #define nmi_count(cpu)			0
 
 #define local_softirq_pending()		(local_cpu_data->softirq_pending)
 #define local_ksoftirqd_task()		(local_cpu_data->ksoftirqd)
-#define really_local_irq_count()	(local_cpu_data->irq_stat.f.irq_count)	/* XXX fix me */
-#define really_local_bh_count()		(local_cpu_data->irq_stat.f.bh_count)	/* XXX fix me */
 #define local_syscall_count()		/* unused on IA-64 */
 #define local_nmi_count()		0
 
 /*
- * 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-31 are the hardirq count (max # of hardirqs: 65536)
+ *
+ * - (bit 63 is the PREEMPT_ACTIVE flag---not currently implemented.)
+ *
+ * PREEMPT_MASK: 0x000000ff
+ * SOFTIRQ_MASK: 0x0000ff00
+ * HARDIRQ_MASK: 0xffff0000
  */
-#define in_interrupt()			(local_cpu_data->irq_stat.irq_and_bh_counts != 0)
-#define in_irq()			(local_cpu_data->irq_stat.f.irq_count != 0)
 
-#ifndef CONFIG_SMP
-# define local_hardirq_trylock()	(really_local_irq_count() == 0)
-# define local_hardirq_endlock()	do { } while (0)
+#define PREEMPT_BITS	8
+#define SOFTIRQ_BITS	8
+#define HARDIRQ_BITS	16
+
+#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 local_irq_enter(irq)		(really_local_irq_count()++)
-# define local_irq_exit(irq)		(really_local_irq_count()--)
+/*
+ * 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 synchronize_irq()		barrier()
+/*
+ * 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()	(!in_interrupt())
+#define hardirq_endlock()	do { } while (0)
+
+#define irq_enter()		(preempt_count() += HARDIRQ_OFFSET)
+
+#if CONFIG_PREEMPT
+# error CONFIG_PREEMT currently not supported.
+# define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1)
 #else
+# define IRQ_EXIT_OFFSET HARDIRQ_OFFSET
+#endif
 
-#include <asm/atomic.h>
-#include <asm/smp.h>
-
-extern unsigned int global_irq_holder;
-extern volatile unsigned long global_irq_lock;
-
-static inline int
-irqs_running (void)
-{
-	int i;
-
-	for (i = 0; i < NR_CPUS; i++)
-		if (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 == cpu) {
-		global_irq_holder = NO_PROC_ID;
-		smp_mb__before_clear_bit();	/* need barrier before releasing lock... */
-		clear_bit(0,&global_irq_lock);
-        }
-}
-
-static inline void
-local_irq_enter (int irq)
-{
-	really_local_irq_count()++;
-
-	while (test_bit(0,&global_irq_lock)) {
-		/* nothing */;
-	}
-}
-
-static inline void
-local_irq_exit (int irq)
-{
-	really_local_irq_count()--;
-}
-
-static inline int
-local_hardirq_trylock (void)
-{
-	return !really_local_irq_count() && !test_bit(0,&global_irq_lock);
-}
-
-#define local_hardirq_endlock()		do { } while (0)
-
-extern void synchronize_irq (void);
+#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)
 
+#ifdef CONFIG_SMP
+  extern void synchronize_irq (unsigned int irq);
+#else
+# define synchronize_irq(irq)	barrier()
 #endif /* CONFIG_SMP */
+
 #endif /* _ASM_IA64_HARDIRQ_H */
diff -Nru a/include/asm-ia64/hw_irq.h b/include/asm-ia64/hw_irq.h
--- a/include/asm-ia64/hw_irq.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/hw_irq.h	Thu Aug  1 01:08:13 2002
@@ -2,10 +2,11 @@
 #define _ASM_IA64_HW_IRQ_H
 
 /*
- * Copyright (C) 2001 Hewlett-Packard Co
- * Copyright (C) 2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 2001-2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
+#include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/types.h>
 
@@ -67,6 +68,8 @@
 
 extern __u8 isa_irq_to_vector_map[16];
 #define isa_irq_to_vector(x)	isa_irq_to_vector_map[(x)]
+extern __u8 gsi_to_vector_map[255];
+#define gsi_to_vector(x)	gsi_to_vector_map[(x)]
 
 extern unsigned long ipi_base_addr;
 
diff -Nru a/include/asm-ia64/keyboard.h b/include/asm-ia64/keyboard.h
--- a/include/asm-ia64/keyboard.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/keyboard.h	Thu Aug  1 01:08:12 2002
@@ -16,6 +16,7 @@
 #define KEYBOARD_IRQ			isa_irq_to_vector(1)
 #define DISABLE_KBD_DURING_INTERRUPTS	0
 
+extern unsigned char acpi_kbd_controller_present;
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
@@ -26,6 +27,7 @@
 extern void pckbd_init_hw(void);
 extern unsigned char pckbd_sysrq_xlate[128];
 
+#define kbd_controller_present() acpi_kbd_controller_present
 #define kbd_setkeycode		pckbd_setkeycode
 #define kbd_getkeycode		pckbd_getkeycode
 #define kbd_pretranslate	pckbd_pretranslate
diff -Nru a/include/asm-ia64/kregs.h b/include/asm-ia64/kregs.h
--- a/include/asm-ia64/kregs.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/kregs.h	Thu Aug  1 01:08:12 2002
@@ -64,6 +64,15 @@
 #define IA64_PSR_RI_BIT		41
 #define IA64_PSR_ED_BIT		43
 #define IA64_PSR_BN_BIT		44
+#define IA64_PSR_IA_BIT		45
+
+/* A mask of PSR bits that we generally don't want to inherit across a clone2() or an
+   execve().  Only list flags here that need to be cleared/set for BOTH clone2() and
+   execve().  */
+#define IA64_PSR_BITS_TO_CLEAR	(IA64_PSR_MFL | IA64_PSR_MFH | IA64_PSR_DB | IA64_PSR_LP | \
+				 IA64_PSR_TB  | IA64_PSR_ID  | IA64_PSR_DA | IA64_PSR_DD | \
+				 IA64_PSR_SS  | IA64_PSR_ED  | IA64_PSR_IA)
+#define IA64_PSR_BITS_TO_SET	(IA64_PSR_DFH)
 
 #define IA64_PSR_BE	(__IA64_UL(1) << IA64_PSR_BE_BIT)
 #define IA64_PSR_UP	(__IA64_UL(1) << IA64_PSR_UP_BIT)
@@ -85,6 +94,7 @@
 #define IA64_PSR_TB	(__IA64_UL(1) << IA64_PSR_TB_BIT)
 #define IA64_PSR_RT	(__IA64_UL(1) << IA64_PSR_RT_BIT)
 /* The following are not affected by save_flags()/restore_flags(): */
+#define IA64_PSR_CPL	(__IA64_UL(3) << IA64_PSR_CPL0_BIT)
 #define IA64_PSR_IS	(__IA64_UL(1) << IA64_PSR_IS_BIT)
 #define IA64_PSR_MC	(__IA64_UL(1) << IA64_PSR_MC_BIT)
 #define IA64_PSR_IT	(__IA64_UL(1) << IA64_PSR_IT_BIT)
@@ -95,6 +105,7 @@
 #define IA64_PSR_RI	(__IA64_UL(3) << IA64_PSR_RI_BIT)
 #define IA64_PSR_ED	(__IA64_UL(1) << IA64_PSR_ED_BIT)
 #define IA64_PSR_BN	(__IA64_UL(1) << IA64_PSR_BN_BIT)
+#define IA64_PSR_IA	(__IA64_UL(1) << IA64_PSR_IA_BIT)
 
 /* User mask bits: */
 #define IA64_PSR_UM	(IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL | IA64_PSR_MFH)
diff -Nru a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
--- a/include/asm-ia64/machvec.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/machvec.h	Thu Aug  1 01:08:12 2002
@@ -210,6 +210,7 @@
 extern ia64_mv_pci_dma_sync_single swiotlb_sync_single;
 extern ia64_mv_pci_dma_sync_sg swiotlb_sync_sg;
 extern ia64_mv_pci_dma_address swiotlb_dma_address;
+extern ia64_mv_pci_dma_supported swiotlb_pci_dma_supported;
 
 /*
  * Define default versions so we can extend machvec for new platforms without having
diff -Nru a/include/asm-ia64/machvec_init.h b/include/asm-ia64/machvec_init.h
--- a/include/asm-ia64/machvec_init.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/machvec_init.h	Thu Aug  1 01:08:12 2002
@@ -16,6 +16,7 @@
 extern ia64_mv_outb_t __ia64_outb;
 extern ia64_mv_outw_t __ia64_outw;
 extern ia64_mv_outl_t __ia64_outl;
+extern ia64_mv_mmiob_t __ia64_mmiob;
 
 #define MACHVEC_HELPER(name)									\
  struct ia64_machine_vector machvec_##name __attribute__ ((unused, __section__ (".machvec")))	\
diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
--- a/include/asm-ia64/mmu_context.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/mmu_context.h	Thu Aug  1 01:08:12 2002
@@ -2,8 +2,8 @@
 #define _ASM_IA64_MMU_CONTEXT_H
 
 /*
- * Copyright (C) 1998-2001 Hewlett-Packard Co
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998-2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 /*
@@ -13,8 +13,6 @@
  * consider the region number when performing a TLB lookup, we need to assign a unique
  * region id to each region in a process.  We use the least significant three bits in a
  * region id for this purpose.
- *
- * Copyright (C) 1998-2001 David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #define IA64_REGION_ID_KERNEL	0 /* the kernel's region id (tlb.c depends on this being 0) */
@@ -23,6 +21,8 @@
 
 # ifndef __ASSEMBLY__
 
+#include <linux/compiler.h>
+#include <linux/percpu.h>
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 
@@ -36,6 +36,7 @@
 };
 
 extern struct ia64_ctx ia64_ctx;
+extern u8 ia64_need_tlb_flush __per_cpu_data;
 
 extern void wrap_mmu_context (struct mm_struct *mm);
 
@@ -44,6 +45,23 @@
 {
 }
 
+/*
+ * When the context counter wraps around all TLBs need to be flushed because an old
+ * context number might have been reused. This is signalled by the ia64_need_tlb_flush
+ * per-CPU variable, which is checked in the routine below. Called by activate_mm().
+ * <efocht@ess.nec.de>
+ */
+static inline void
+delayed_tlb_flush (void)
+{
+	extern void __flush_tlb_all (void);
+
+	if (unlikely(ia64_need_tlb_flush)) {
+		__flush_tlb_all();
+		ia64_need_tlb_flush = 0;
+	}
+}
+
 static inline void
 get_new_mmu_context (struct mm_struct *mm)
 {
@@ -54,7 +72,6 @@
 		mm->context = ia64_ctx.next++;
 	}
 	spin_unlock(&ia64_ctx.lock);
-
 }
 
 static inline void
@@ -109,6 +126,8 @@
 static inline void
 activate_mm (struct mm_struct *prev, struct mm_struct *next)
 {
+	delayed_tlb_flush();
+
 	/*
 	 * We may get interrupts here, but that's OK because interrupt
 	 * handlers cannot touch user-space.
diff -Nru a/include/asm-ia64/offsets.h b/include/asm-ia64/offsets.h
--- a/include/asm-ia64/offsets.h	Thu Aug  1 01:08:13 2002
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,130 +0,0 @@
-#ifndef _ASM_IA64_OFFSETS_H
-#define _ASM_IA64_OFFSETS_H
-/*
- * DO NOT MODIFY
- *
- * This file was generated by arch/ia64/tools/print_offsets.awk.
- *
- */
-#define IA64_TASK_SIZE			3952	/* 0xf70 */
-#define IA64_THREAD_INFO_SIZE		32	/* 0x20 */
-#define IA64_PT_REGS_SIZE		400	/* 0x190 */
-#define IA64_SWITCH_STACK_SIZE		560	/* 0x230 */
-#define IA64_SIGINFO_SIZE		128	/* 0x80 */
-#define IA64_CPU_SIZE			224	/* 0xe0 */
-#define SIGFRAME_SIZE			2816	/* 0xb00 */
-#define UNW_FRAME_INFO_SIZE		448	/* 0x1c0 */
-
-#define IA64_TASK_THREAD_KSP_OFFSET	1496	/* 0x5d8 */
-#define IA64_PT_REGS_CR_IPSR_OFFSET	0	/* 0x0 */
-#define IA64_PT_REGS_CR_IIP_OFFSET	8	/* 0x8 */
-#define IA64_PT_REGS_CR_IFS_OFFSET	16	/* 0x10 */
-#define IA64_PT_REGS_AR_UNAT_OFFSET	24	/* 0x18 */
-#define IA64_PT_REGS_AR_PFS_OFFSET	32	/* 0x20 */
-#define IA64_PT_REGS_AR_RSC_OFFSET	40	/* 0x28 */
-#define IA64_PT_REGS_AR_RNAT_OFFSET	48	/* 0x30 */
-#define IA64_PT_REGS_AR_BSPSTORE_OFFSET	56	/* 0x38 */
-#define IA64_PT_REGS_PR_OFFSET		64	/* 0x40 */
-#define IA64_PT_REGS_B6_OFFSET		72	/* 0x48 */
-#define IA64_PT_REGS_LOADRS_OFFSET	80	/* 0x50 */
-#define IA64_PT_REGS_R1_OFFSET		88	/* 0x58 */
-#define IA64_PT_REGS_R2_OFFSET		96	/* 0x60 */
-#define IA64_PT_REGS_R3_OFFSET		104	/* 0x68 */
-#define IA64_PT_REGS_R12_OFFSET		112	/* 0x70 */
-#define IA64_PT_REGS_R13_OFFSET		120	/* 0x78 */
-#define IA64_PT_REGS_R14_OFFSET		128	/* 0x80 */
-#define IA64_PT_REGS_R15_OFFSET		136	/* 0x88 */
-#define IA64_PT_REGS_R8_OFFSET		144	/* 0x90 */
-#define IA64_PT_REGS_R9_OFFSET		152	/* 0x98 */
-#define IA64_PT_REGS_R10_OFFSET		160	/* 0xa0 */
-#define IA64_PT_REGS_R11_OFFSET		168	/* 0xa8 */
-#define IA64_PT_REGS_R16_OFFSET		176	/* 0xb0 */
-#define IA64_PT_REGS_R17_OFFSET		184	/* 0xb8 */
-#define IA64_PT_REGS_R18_OFFSET		192	/* 0xc0 */
-#define IA64_PT_REGS_R19_OFFSET		200	/* 0xc8 */
-#define IA64_PT_REGS_R20_OFFSET		208	/* 0xd0 */
-#define IA64_PT_REGS_R21_OFFSET		216	/* 0xd8 */
-#define IA64_PT_REGS_R22_OFFSET		224	/* 0xe0 */
-#define IA64_PT_REGS_R23_OFFSET		232	/* 0xe8 */
-#define IA64_PT_REGS_R24_OFFSET		240	/* 0xf0 */
-#define IA64_PT_REGS_R25_OFFSET		248	/* 0xf8 */
-#define IA64_PT_REGS_R26_OFFSET		256	/* 0x100 */
-#define IA64_PT_REGS_R27_OFFSET		264	/* 0x108 */
-#define IA64_PT_REGS_R28_OFFSET		272	/* 0x110 */
-#define IA64_PT_REGS_R29_OFFSET		280	/* 0x118 */
-#define IA64_PT_REGS_R30_OFFSET		288	/* 0x120 */
-#define IA64_PT_REGS_R31_OFFSET		296	/* 0x128 */
-#define IA64_PT_REGS_AR_CCV_OFFSET	304	/* 0x130 */
-#define IA64_PT_REGS_AR_FPSR_OFFSET	312	/* 0x138 */
-#define IA64_PT_REGS_B0_OFFSET		320	/* 0x140 */
-#define IA64_PT_REGS_B7_OFFSET		328	/* 0x148 */
-#define IA64_PT_REGS_F6_OFFSET		336	/* 0x150 */
-#define IA64_PT_REGS_F7_OFFSET		352	/* 0x160 */
-#define IA64_PT_REGS_F8_OFFSET		368	/* 0x170 */
-#define IA64_PT_REGS_F9_OFFSET		384	/* 0x180 */
-#define IA64_SWITCH_STACK_CALLER_UNAT_OFFSET 0	/* 0x0 */
-#define IA64_SWITCH_STACK_AR_FPSR_OFFSET 8	/* 0x8 */
-#define IA64_SWITCH_STACK_F2_OFFSET	16	/* 0x10 */
-#define IA64_SWITCH_STACK_F3_OFFSET	32	/* 0x20 */
-#define IA64_SWITCH_STACK_F4_OFFSET	48	/* 0x30 */
-#define IA64_SWITCH_STACK_F5_OFFSET	64	/* 0x40 */
-#define IA64_SWITCH_STACK_F10_OFFSET	80	/* 0x50 */
-#define IA64_SWITCH_STACK_F11_OFFSET	96	/* 0x60 */
-#define IA64_SWITCH_STACK_F12_OFFSET	112	/* 0x70 */
-#define IA64_SWITCH_STACK_F13_OFFSET	128	/* 0x80 */
-#define IA64_SWITCH_STACK_F14_OFFSET	144	/* 0x90 */
-#define IA64_SWITCH_STACK_F15_OFFSET	160	/* 0xa0 */
-#define IA64_SWITCH_STACK_F16_OFFSET	176	/* 0xb0 */
-#define IA64_SWITCH_STACK_F17_OFFSET	192	/* 0xc0 */
-#define IA64_SWITCH_STACK_F18_OFFSET	208	/* 0xd0 */
-#define IA64_SWITCH_STACK_F19_OFFSET	224	/* 0xe0 */
-#define IA64_SWITCH_STACK_F20_OFFSET	240	/* 0xf0 */
-#define IA64_SWITCH_STACK_F21_OFFSET	256	/* 0x100 */
-#define IA64_SWITCH_STACK_F22_OFFSET	272	/* 0x110 */
-#define IA64_SWITCH_STACK_F23_OFFSET	288	/* 0x120 */
-#define IA64_SWITCH_STACK_F24_OFFSET	304	/* 0x130 */
-#define IA64_SWITCH_STACK_F25_OFFSET	320	/* 0x140 */
-#define IA64_SWITCH_STACK_F26_OFFSET	336	/* 0x150 */
-#define IA64_SWITCH_STACK_F27_OFFSET	352	/* 0x160 */
-#define IA64_SWITCH_STACK_F28_OFFSET	368	/* 0x170 */
-#define IA64_SWITCH_STACK_F29_OFFSET	384	/* 0x180 */
-#define IA64_SWITCH_STACK_F30_OFFSET	400	/* 0x190 */
-#define IA64_SWITCH_STACK_F31_OFFSET	416	/* 0x1a0 */
-#define IA64_SWITCH_STACK_R4_OFFSET	432	/* 0x1b0 */
-#define IA64_SWITCH_STACK_R5_OFFSET	440	/* 0x1b8 */
-#define IA64_SWITCH_STACK_R6_OFFSET	448	/* 0x1c0 */
-#define IA64_SWITCH_STACK_R7_OFFSET	456	/* 0x1c8 */
-#define IA64_SWITCH_STACK_B0_OFFSET	464	/* 0x1d0 */
-#define IA64_SWITCH_STACK_B1_OFFSET	472	/* 0x1d8 */
-#define IA64_SWITCH_STACK_B2_OFFSET	480	/* 0x1e0 */
-#define IA64_SWITCH_STACK_B3_OFFSET	488	/* 0x1e8 */
-#define IA64_SWITCH_STACK_B4_OFFSET	496	/* 0x1f0 */
-#define IA64_SWITCH_STACK_B5_OFFSET	504	/* 0x1f8 */
-#define IA64_SWITCH_STACK_AR_PFS_OFFSET	512	/* 0x200 */
-#define IA64_SWITCH_STACK_AR_LC_OFFSET	520	/* 0x208 */
-#define IA64_SWITCH_STACK_AR_UNAT_OFFSET 528	/* 0x210 */
-#define IA64_SWITCH_STACK_AR_RNAT_OFFSET 536	/* 0x218 */
-#define IA64_SWITCH_STACK_AR_BSPSTORE_OFFSET 544	/* 0x220 */
-#define IA64_SWITCH_STACK_PR_OFFSET	552	/* 0x228 */
-#define IA64_SIGCONTEXT_IP_OFFSET	40	/* 0x28 */
-#define IA64_SIGCONTEXT_AR_BSP_OFFSET	72	/* 0x48 */
-#define IA64_SIGCONTEXT_AR_FPSR_OFFSET	104	/* 0x68 */
-#define IA64_SIGCONTEXT_AR_RNAT_OFFSET	80	/* 0x50 */
-#define IA64_SIGCONTEXT_AR_UNAT_OFFSET	96	/* 0x60 */
-#define IA64_SIGCONTEXT_B0_OFFSET	136	/* 0x88 */
-#define IA64_SIGCONTEXT_CFM_OFFSET	48	/* 0x30 */
-#define IA64_SIGCONTEXT_FLAGS_OFFSET	0	/* 0x0 */
-#define IA64_SIGCONTEXT_FR6_OFFSET	560	/* 0x230 */
-#define IA64_SIGCONTEXT_PR_OFFSET	128	/* 0x80 */
-#define IA64_SIGCONTEXT_R12_OFFSET	296	/* 0x128 */
-#define IA64_SIGCONTEXT_RBS_BASE_OFFSET	2512	/* 0x9d0 */
-#define IA64_SIGCONTEXT_LOADRS_OFFSET	2520	/* 0x9d8 */
-#define IA64_SIGFRAME_ARG0_OFFSET	0	/* 0x0 */
-#define IA64_SIGFRAME_ARG1_OFFSET	8	/* 0x8 */
-#define IA64_SIGFRAME_ARG2_OFFSET	16	/* 0x10 */
-#define IA64_SIGFRAME_HANDLER_OFFSET	24	/* 0x18 */
-#define IA64_SIGFRAME_SIGCONTEXT_OFFSET	160	/* 0xa0 */
-#define IA64_CLONE_VFORK		16384	/* 0x4000 */
-#define IA64_CLONE_VM			256	/* 0x100 */
-
-#endif /* _ASM_IA64_OFFSETS_H */
diff -Nru a/include/asm-ia64/param.h b/include/asm-ia64/param.h
--- a/include/asm-ia64/param.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/param.h	Thu Aug  1 01:08:13 2002
@@ -4,8 +4,8 @@
 /*
  * Fundamental kernel parameters.
  *
- * Copyright (C) 1998, 1999 Hewlett-Packard Co
- * Copyright (C) 1998, 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+ * Copyright (C) 1998, 1999, 2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
 #include <linux/config.h>
@@ -33,6 +33,7 @@
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
 
 #ifdef __KERNEL__
+# define USER_HZ	HZ
 # define CLOCKS_PER_SEC	HZ	/* frequency at which times() counts */
 #endif
 
diff -Nru a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
--- a/include/asm-ia64/pci.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/pci.h	Thu Aug  1 01:08:13 2002
@@ -21,7 +21,7 @@
 #define PCIBIOS_MIN_MEM		0x10000000
 
 void pcibios_config_init(void);
-struct pci_bus * pcibios_scan_root(int seg, int bus);
+struct pci_bus * pcibios_scan_root(int bus);
 extern int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value);
 extern int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value);
 
@@ -90,7 +90,7 @@
 /* Return the index of the PCI controller for device PDEV. */
 #define pci_controller_num(PDEV)	(0)
 
-#define sg_dma_len(sg)		((sg)->length)
+#define sg_dma_len(sg)		((sg)->dma_length)
 
 #define HAVE_PCI_MMAP
 extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
diff -Nru a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h
--- a/include/asm-ia64/perfmon.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/perfmon.h	Thu Aug  1 01:08:13 2002
@@ -172,9 +172,8 @@
 extern int  pfm_release_debug_registers(struct task_struct *);
 extern int  pfm_cleanup_smpl_buf(struct task_struct *);
 extern void pfm_syst_wide_update_task(struct task_struct *, int);
-extern void pfm_ovfl_block_reset (void);
-
-extern int pfm_syst_wide;
+extern void pfm_ovfl_block_reset(void);
+extern void perfmon_init_percpu(void);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
--- a/include/asm-ia64/pgalloc.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/pgalloc.h	Thu Aug  1 01:08:12 2002
@@ -15,9 +15,10 @@
 
 #include <linux/config.h>
 
+#include <linux/compiler.h>
 #include <linux/mm.h>
+#include <linux/page-flags.h>
 #include <linux/threads.h>
-#include <linux/compiler.h>
 
 #include <asm/mmu_context.h>
 #include <asm/processor.h>
diff -Nru a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
--- a/include/asm-ia64/processor.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/processor.h	Thu Aug  1 01:08:13 2002
@@ -270,12 +270,8 @@
 
 #define start_thread(regs,new_ip,new_sp) do {							\
 	set_fs(USER_DS);									\
-	ia64_psr(regs)->dfh = 1;	/* disable fph */					\
-	ia64_psr(regs)->mfh = 0;	/* clear mfh */						\
-	ia64_psr(regs)->cpl = 3;	/* set user mode */					\
-	ia64_psr(regs)->ri = 0;		/* clear return slot number */				\
-	ia64_psr(regs)->is = 0;		/* IA-64 instruction set */				\
-	ia64_psr(regs)->sp = 1;		/* enforce secure perfmon */				\
+	regs->cr_ipsr = ((regs->cr_ipsr | (IA64_PSR_BITS_TO_SET | IA64_PSR_CPL | IA64_PSR_SP))	\
+			 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_RI | IA64_PSR_IS));		\
 	regs->cr_iip = new_ip;									\
 	regs->ar_rsc = 0xf;		/* eager mode, privilege level 3 */			\
 	regs->ar_rnat = 0;									\
@@ -284,7 +280,7 @@
 	regs->loadrs = 0;									\
 	regs->r8 = current->mm->dumpable;	/* set "don't zap registers" flag */		\
 	regs->r12 = new_sp - 16;	/* allocate 16 byte scratch area */			\
-	if (!likely (current->mm->dumpable)) {					\
+	if (unlikely(!current->mm->dumpable)) {					\
 		/*										\
 		 * Zap scratch regs to avoid leaking bits between processes with different	\
 		 * uid/privileges.								\
diff -Nru a/include/asm-ia64/rmap.h b/include/asm-ia64/rmap.h
--- a/include/asm-ia64/rmap.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/rmap.h	Thu Aug  1 01:08:13 2002
@@ -1,7 +1,7 @@
-#ifndef _IA64_RMAP_H
-#define _IA64_RMAP_H
+#ifndef _ASM_IA64_RMAP_H
+#define _ASM_IA64_RMAP_H
 
 /* nothing to see, move along */
 #include <asm-generic/rmap.h>
 
-#endif
+#endif /* _ASM_IA64_RMAP_H */
diff -Nru a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h
--- a/include/asm-ia64/scatterlist.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/scatterlist.h	Thu Aug  1 01:08:13 2002
@@ -7,12 +7,12 @@
  */
 
 struct scatterlist {
-	char *orig_address;	/* for use by swiotlb */
-
-	/* These two are only valid if ADDRESS member of this struct is NULL.  */
 	struct page *page;
 	unsigned int offset;
 	unsigned int length;	/* buffer length */
+
+	dma_addr_t dma_address;
+	unsigned int dma_length;
 };
 
 #define ISA_DMA_THRESHOLD	(~0UL)
diff -Nru a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
--- a/include/asm-ia64/smp.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/smp.h	Thu Aug  1 01:08:13 2002
@@ -17,6 +17,7 @@
 #include <linux/threads.h>
 #include <linux/kernel.h>
 
+#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/param.h>
 #include <asm/processor.h>
@@ -36,6 +37,7 @@
 
 extern char no_int_routing __initdata;
 
+extern unsigned long phys_cpu_present_map;
 extern volatile unsigned long cpu_online_map;
 extern unsigned long ipi_base_addr;
 extern unsigned char smp_int_redirect;
@@ -45,23 +47,26 @@
 
 extern unsigned long ap_wakeup_vector;
 
-#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
-extern inline unsigned int num_online_cpus(void)
+#define cpu_possible(cpu)	(phys_cpu_present_map & (1UL << (cpu)))
+#define cpu_online(cpu)		(cpu_online_map & (1UL << (cpu)))
+
+static inline unsigned int
+num_online_cpus (void)
 {
 	return hweight64(cpu_online_map);
 }
 
-extern inline int any_online_cpu(unsigned int mask)
+static inline int
+any_online_cpu (unsigned int mask)
 {
 	if (mask & cpu_online_map)
 		return __ffs(mask & cpu_online_map);
-
 	return -1;
 }
 
 /*
- * Function to map hard smp processor id to logical id.  Slow, so
- * don't use this in performance-critical code.
+ * Function to map hard smp processor id to logical id.  Slow, so don't use this in
+ * performance-critical code.
  */
 static inline int
 cpu_logical_id (int cpuid)
@@ -120,11 +125,9 @@
 }
 
 /* Upping and downing of CPUs */
-extern int __cpu_disable(void);
-extern void __cpu_die(unsigned int cpu);
-extern int __cpu_up(unsigned int cpu);
-
-#define NO_PROC_ID		0xffffffff	/* no processor magic marker */
+extern int __cpu_disable (void);
+extern void __cpu_die (unsigned int cpu);
+extern int __cpu_up (unsigned int cpu);
 
 extern void __init init_smp_config (void);
 extern void smp_do_timer (struct pt_regs *regs);
diff -Nru a/include/asm-ia64/smplock.h b/include/asm-ia64/smplock.h
--- a/include/asm-ia64/smplock.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/smplock.h	Thu Aug  1 01:08:13 2002
@@ -14,11 +14,6 @@
 
 #ifdef CONFIG_SMP
 # define kernel_locked()	spin_is_locked(&kernel_flag)
-# define check_irq_holder(cpu)			\
-do {						\
-	if (global_irq_holder == (cpu))		\
-		BUG();				\
-} while (0)
 #else
 # define kernel_locked()	(1)
 #endif
@@ -26,12 +21,10 @@
 /*
  * Release global kernel lock and global interrupt lock
  */
-#define release_kernel_lock(task, cpu)		\
+#define release_kernel_lock(task)		\
 do {						\
-	if (unlikely(task->lock_depth >= 0)) {	\
+	if (unlikely(task->lock_depth >= 0))	\
 		spin_unlock(&kernel_flag);	\
-		check_irq_holder(cpu);		\
-	}					\
 } while (0)
 
 /*
diff -Nru a/include/asm-ia64/softirq.h b/include/asm-ia64/softirq.h
--- a/include/asm-ia64/softirq.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/softirq.h	Thu Aug  1 01:08:13 2002
@@ -4,22 +4,23 @@
 #include <linux/compiler.h>
 
 /*
- * Copyright (C) 1998-2001 Hewlett-Packard Co
+ * Copyright (C) 1998-2002 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
+#include <linux/compiler.h>
+#include <linux/preempt.h>
+
 #include <asm/hardirq.h>
 
-#define __local_bh_enable()	do { barrier(); really_local_bh_count()--; } while (0)
+#define __local_bh_enable()	do { barrier(); preempt_count() -= SOFTIRQ_OFFSET; } while (0)
 
-#define local_bh_disable()	do { really_local_bh_count()++; barrier(); } while (0)
-#define local_bh_enable()								\
-do {											\
-	__local_bh_enable();								\
-	if (unlikely(local_softirq_pending()) && really_local_bh_count() == 0)	\
-		do_softirq();								\
+#define local_bh_disable()	do { preempt_count() += SOFTIRQ_OFFSET; barrier(); } while (0)
+#define local_bh_enable()						\
+do {									\
+	__local_bh_enable();						\
+	if (unlikely(!in_interrupt() && local_softirq_pending()))	\
+		do_softirq();						\
+	preempt_check_resched();					\
 } while (0)
-
-
-#define in_softirq()		(really_local_bh_count() != 0)
 
 #endif /* _ASM_IA64_SOFTIRQ_H */
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/system.h	Thu Aug  1 01:08:13 2002
@@ -13,9 +13,11 @@
  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
  */
 #include <linux/config.h>
+#include <linux/percpu.h>
 
 #include <asm/kregs.h>
 #include <asm/page.h>
+#include <asm/pal.h>
 
 #define KERNEL_START		(PAGE_OFFSET + 68*1024*1024)
 
@@ -102,6 +104,8 @@
 #define set_mb(var, value)	do { (var) = (value); mb(); } while (0)
 #define set_wmb(var, value)	do { (var) = (value); mb(); } while (0)
 
+#define safe_halt()         ia64_pal_halt(1)                /* PAL_HALT */
+
 /*
  * The group barrier in front of the rsm & ssm are necessary to ensure
  * that none of the previous instructions in the same group are
@@ -168,27 +172,7 @@
 #endif /* !CONFIG_IA64_DEBUG_IRQ */
 
 #define local_irq_enable()	__asm__ __volatile__ (";; ssm psr.i;; srlz.d" ::: "memory")
-
-#define local_irq_disable()			local_irq_disable ()
 #define local_save_flags(flags)	__asm__ __volatile__ ("mov %0=psr" : "=r" (flags) :: "memory")
-#define local_irq_save(flags)	local_irq_save(flags)
-#define save_and_cli(flags)	local_irq_save(flags)
-
-#ifdef 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(flags)	((flags) = __global_save_flags())
-# define restore_flags(flags)	__global_restore_flags(flags)
-#else /* !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)
-#endif /* !CONFIG_SMP */
 
 /*
  * Force an unresolved reference if someone tries to use
@@ -376,7 +360,7 @@
  * newly created thread returns directly to
  * ia64_ret_from_syscall_clear_r8.
  */
-extern void ia64_switch_to (void *next_task);
+extern struct task_struct *ia64_switch_to (void *next_task);
 
 struct task_struct;
 
@@ -384,19 +368,20 @@
 extern void ia64_load_extra (struct task_struct *task);
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PERFMON)
-# define PERFMON_IS_SYSWIDE() (local_cpu_data->pfm_syst_wide != 0)
+  extern int __per_cpu_data pfm_syst_wide;
+# define PERFMON_IS_SYSWIDE() (this_cpu(pfm_syst_wide) != 0)
 #else
 # define PERFMON_IS_SYSWIDE() (0)
 #endif
 
-#define __switch_to(prev,next) do {							\
+#define __switch_to(prev,next,last) do {							\
 	if (((prev)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))	\
 	    || IS_IA32_PROCESS(ia64_task_regs(prev)) || PERFMON_IS_SYSWIDE())		\
 		ia64_save_extra(prev);							\
 	if (((next)->thread.flags & (IA64_THREAD_DBG_VALID|IA64_THREAD_PM_VALID))	\
 	    || IS_IA32_PROCESS(ia64_task_regs(next)) || PERFMON_IS_SYSWIDE())		\
 		ia64_load_extra(next);							\
-	ia64_switch_to((next));								\
+	(last) = ia64_switch_to((next));						\
 } while (0)
 
 #ifdef CONFIG_SMP
@@ -411,19 +396,19 @@
  * task->thread.fph, avoiding the complication of having to fetch
  * the latest fph state from another CPU.
  */
-# define switch_to(prev,next) do {						\
+# define switch_to(prev,next,last) do {						\
 	if (ia64_psr(ia64_task_regs(prev))->mfh) {				\
 		ia64_psr(ia64_task_regs(prev))->mfh = 0;			\
 		(prev)->thread.flags |= IA64_THREAD_FPH_VALID;			\
 		__ia64_save_fpu((prev)->thread.fph);				\
 	}									\
 	ia64_psr(ia64_task_regs(prev))->dfh = 1;				\
-	__switch_to(prev,next);							\
+	__switch_to(prev,next,last);						\
   } while (0)
 #else
-# define switch_to(prev,next) do {						\
+# define switch_to(prev,next,last) do {						\
 	ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next));	\
-	__switch_to(prev,next);							\
+	__switch_to(prev,next,last);						\
 } while (0)
 #endif
 
diff -Nru a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
--- a/include/asm-ia64/tlb.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/tlb.h	Thu Aug  1 01:08:13 2002
@@ -1,7 +1,195 @@
-/* XXX fix me! */
+#ifndef _ASM_IA64_TLB_H
+#define _ASM_IA64_TLB_H
+/*
+ * Copyright (C) 2002 Hewlett-Packard Co
+ *	David Mosberger-Tang <davidm@hpl.hp.com>
+ *
+ * This file was derived from asm-generic/tlb.h.
+ */
+/*
+ * Removing a translation from a page table (including TLB-shootdown) is a four-step
+ * procedure:
+ *
+ *	(1) Flush (virtual) caches --- ensures virtual memory is coherent with kernel memory
+ *	    (this is a no-op on ia64).
+ *	(2) Clear the relevant portions of the page-table
+ *	(3) Flush the TLBs --- ensures that stale content is gone from CPU TLBs
+ *	(4) Release the pages that were freed up in step (2).
+ *
+ * Note that the ordering of these steps is crucial to avoid races on MP machines.
+ *
+ * The Linux kernel defines several platform-specific hooks for TLB-shootdown.  When
+ * unmapping a portion of the virtual address space, these hooks are called according to
+ * the following template:
+ *
+ *	tlb <- tlb_gather_mmu(mm, full_mm_flush);	// start unmap for address space MM
+ *	{
+ *	  for each vma that needs a shootdown do {
+ *	    tlb_start_vma(tlb, vma);
+ *	      for each page-table-entry PTE that needs to be removed do {
+ *		tlb_remove_tlb_entry(tlb, pte, address);
+ *		if (pte refers to a normal page) {
+ *		  tlb_remove_page(tlb, page);
+ *		}
+ *	      }
+ *	    tlb_end_vma(tlb, vma);
+ *	  }
+ *	}
+ *	tlb_finish_mmu(tlb, start, end);	// finish unmap for address space MM
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+
+#include <asm/processor.h>
+#include <asm/tlbflush.h>
+
+#ifdef CONFIG_SMP
+# define FREE_PTE_NR		2048
+# define tlb_fast_mode(tlb)	((tlb)->nr == ~0U)
+#else
+# define FREE_PTE_NR		0
+# define tlb_fast_mode(tlb)	(1)
+#endif
+
+typedef struct {
+	struct mm_struct	*mm;
+	unsigned int		nr;	/* == ~0U => fast mode */
+	unsigned int		fullmm;	/* non-zero means full mm flush */
+	unsigned long		freed;	/* number of pages freed */
+	unsigned long		start_addr;
+	unsigned long		end_addr;
+	struct page 		*pages[FREE_PTE_NR];
+} mmu_gather_t;
+
+/* Users of the generic TLB shootdown code must declare this storage space. */
+extern mmu_gather_t	mmu_gathers[NR_CPUS];
+
+/*
+ * Flush the TLB for address range START to END and, if not in fast mode, release the
+ * freed pages that where gathered up to this point.
+ */
+static inline void
+ia64_tlb_flush_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end)
+{
+	unsigned int nr;
+
+	if (tlb->fullmm) {
+		/*
+		 * Tearing down the entire address space.  This happens both as a result
+		 * of exit() and execve().  The latter case necessitates the call to
+		 * flush_tlb_mm() here.
+		 */
+		flush_tlb_mm(tlb->mm);
+	} else if (unlikely (end - start >= 1024*1024*1024*1024UL
+		      || REGION_NUMBER(start) != REGION_NUMBER(end - 1)))
+	{
+		/*
+		 * If we flush more than a tera-byte or across regions, we're probably
+		 * better off just flushing the entire TLB(s).  This should be very rare
+		 * and is not worth optimizing for.
+		 */
+		flush_tlb_all();
+	} else {
+		/*
+		 * XXX fix me: flush_tlb_range() should take an mm pointer instead of a
+		 * vma pointer.
+		 */
+		struct vm_area_struct vma;
+
+		vma.vm_mm = tlb->mm;
+		/* flush the address range from the tlb: */
+		flush_tlb_range(&vma, start, end);
+		/* now flush the virt. page-table area mapping the address range: */
+		flush_tlb_range(&vma, ia64_thash(start), ia64_thash(end));
+	}
+
+	/* lastly, release the freed pages */
+	nr = tlb->nr;
+	if (!tlb_fast_mode(tlb)) {
+		unsigned long i;
+		tlb->nr = 0;
+		tlb->start_addr = ~0UL;
+		for (i = 0; i < nr; ++i)
+			free_page_and_swap_cache(tlb->pages[i]);
+	}
+}
+
+/*
+ * Return a pointer to an initialized mmu_gather_t.
+ */
+static inline mmu_gather_t *
+tlb_gather_mmu (struct mm_struct *mm, unsigned int full_mm_flush)
+{
+	mmu_gather_t *tlb = &mmu_gathers[smp_processor_id()];
+
+	tlb->mm = mm;
+	tlb->nr = 0;
+	if (full_mm_flush || num_online_cpus() == 1)
+		/*
+		 * Use fast mode if only 1 CPU is online or if we're tearing down the
+		 * entire address space.
+		 */
+		tlb->nr =  ~0U;
+	tlb->fullmm = full_mm_flush;
+	tlb->freed = 0;
+	tlb->start_addr = ~0UL;
+	return tlb;
+}
+
+/*
+ * Called at the end of the shootdown operation to free up any resources that were
+ * collected.  The page table lock is still held at this point.
+ */
+static inline void
+tlb_finish_mmu (mmu_gather_t *tlb, unsigned long start, unsigned long end)
+{
+	unsigned long freed = tlb->freed;
+	struct mm_struct *mm = tlb->mm;
+	unsigned long rss = mm->rss;
+
+	if (rss < freed)
+		freed = rss;
+	mm->rss = rss - freed;
+	/*
+	 * Note: tlb->nr may be 0 at this point, so we can't rely on tlb->start_addr and
+	 * tlb->end_addr.
+	 */
+	ia64_tlb_flush_mmu(tlb, start, end);
+
+	/* keep the page table cache within bounds */
+	check_pgt_cache();
+}
+
+/*
+ * Remove TLB entry for PTE mapped at virtual address ADDRESS.  This is called for any
+ * PTE, not just those pointing to (normal) physical memory.
+ */
+static inline void
+tlb_remove_tlb_entry (mmu_gather_t *tlb, pte_t *ptep, unsigned long address)
+{
+	if (tlb->start_addr == ~0UL)
+		tlb->start_addr = address;
+	tlb->end_addr = address + PAGE_SIZE;
+}
+
+/*
+ * Logically, this routine frees PAGE.  On MP machines, the actual freeing of the page
+ * must be delayed until after the TLB has been flushed (see comments at the beginning of
+ * this file).
+ */
+static inline void
+tlb_remove_page (mmu_gather_t *tlb, struct page *page)
+{
+	if (tlb_fast_mode(tlb)) {
+		free_page_and_swap_cache(page);
+		return;
+	}
+	tlb->pages[tlb->nr++] = page;
+	if (tlb->nr >= FREE_PTE_NR)
+		ia64_tlb_flush_mmu(tlb, tlb->start_addr, tlb->end_addr);
+}
+
 #define tlb_start_vma(tlb, vma)			do { } while (0)
 #define tlb_end_vma(tlb, vma)			do { } while (0)
-#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
-#define tlb_flush(tlb)				flush_tlb_mm((tlb)->mm)
 
-#include <asm-generic/tlb.h>
+#endif /* _ASM_IA64_TLB_H */
diff -Nru a/include/asm-ia64/tlbflush.h b/include/asm-ia64/tlbflush.h
--- a/include/asm-ia64/tlbflush.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ia64/tlbflush.h	Thu Aug  1 01:08:13 2002
@@ -70,12 +70,10 @@
 static inline void
 flush_tlb_pgtables (struct mm_struct *mm, unsigned long start, unsigned long end)
 {
-	struct vm_area_struct vma;
-
-	if (REGION_NUMBER(start) != REGION_NUMBER(end))
-		printk("flush_tlb_pgtables: can't flush across regions!!\n");
-	vma.vm_mm = mm;
-	flush_tlb_range(&vma, ia64_thash(start), ia64_thash(end));
+	/*
+	 * Deprecated.  The virtual page table is now flushed via the normal gather/flush
+	 * interface (see tlb.h).
+	 */
 }
 
 #define flush_tlb_kernel_range(start, end)	flush_tlb_all()	/* XXX fix me */
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ia64/unistd.h	Thu Aug  1 01:08:12 2002
@@ -223,6 +223,10 @@
 #define __NR_sched_setaffinity		1231
 #define __NR_sched_getaffinity		1232
 #define __NR_security			1233
+#define __NR_get_large_pages		1234
+#define __NR_free_large_pages		1235
+#define __NR_share_large_pages		1236
+#define __NR_unshare_large_pages	1237
 
 #if !defined(__ASSEMBLY__) && !defined(ASSEMBLER)
 
diff -Nru a/include/asm-ppc/hardirq.h b/include/asm-ppc/hardirq.h
--- a/include/asm-ppc/hardirq.h	Thu Aug  1 01:08:12 2002
+++ b/include/asm-ppc/hardirq.h	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/include/asm-ppc/hw_irq.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/asm-ppc/pgtable.h	Thu Aug  1 01:08:12 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/rwsem.h b/include/asm-ppc/rwsem.h
--- a/include/asm-ppc/rwsem.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ppc/rwsem.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/asm-ppc/smplock.h	Thu Aug  1 01:08:12 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/softirq.h b/include/asm-ppc/softirq.h
--- a/include/asm-ppc/softirq.h	Thu Aug  1 01:08:13 2002
+++ b/include/asm-ppc/softirq.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/asm-ppc/system.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/asm-ppc/thread_info.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/asm-ppc/tlb.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/asm-ppc/tlbflush.h	Thu Aug  1 01:08:12 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/linux/devfs_fs_kernel.h b/include/linux/devfs_fs_kernel.h
--- a/include/linux/devfs_fs_kernel.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/devfs_fs_kernel.h	Thu Aug  1 01:08:13 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, 
@@ -164,14 +164,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)
 {
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	Thu Aug  1 01:08:12 2002
+++ b/include/linux/fs.h	Thu Aug  1 01:08:12 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> */
@@ -509,12 +513,17 @@
 
 extern int init_private_file(struct file *, struct dentry *, int);
 
+/* Max fileoffset that can safely be dealt with by filesystems that have not (yet) been
+   audited for 64-bit issues. */
 #define	MAX_NON_LFS	((1UL<<31) - 1)
 
-/* Page cache limit. The filesystems should put that into their s_maxbytes 
-   limits, otherwise bad things can happen in VM. */ 
+/* Max fileoffset that can be stored in a variable of type offset_t.  */
+#define MAX_OFF_T	((loff_t)((1UL << ((sizeof(off_t)*8) - 1)) - 1))
+
+/* Page cache limit. The filesystems should put that into their s_maxbytes
+   limits, otherwise bad things can happen in VM. */
 #if BITS_PER_LONG==32
-#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) 
+#define MAX_LFS_FILESIZE	(((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1)
 #elif BITS_PER_LONG==64
 #define MAX_LFS_FILESIZE 	0x7fffffffffffffff
 #endif
@@ -757,6 +766,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 +1244,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/highmem.h b/include/linux/highmem.h
--- a/include/linux/highmem.h	Thu Aug  1 01:08:12 2002
+++ b/include/linux/highmem.h	Thu Aug  1 01:08:12 2002
@@ -3,6 +3,8 @@
 
 #include <linux/config.h>
 #include <linux/fs.h>
+#include <linux/mm.h>
+
 #include <asm/cacheflush.h>
 
 #ifdef CONFIG_HIGHMEM
diff -Nru a/include/linux/irq.h b/include/linux/irq.h
--- a/include/linux/irq.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/irq.h	Thu Aug  1 01:08:13 2002
@@ -56,15 +56,13 @@
  *
  * Pad this out to 32 bytes for cache and indexing reasons.
  */
-typedef struct {
+typedef struct irq_desc {
 	unsigned int status;		/* IRQ status */
 	hw_irq_controller *handler;
 	struct irqaction *action;	/* IRQ action list */
 	unsigned int depth;		/* nested irq disables */
 	spinlock_t lock;
 } ____cacheline_aligned irq_desc_t;
-
-extern irq_desc_t irq_desc [NR_IRQS];
 
 #include <asm/hw_irq.h> /* the arch dependent stuff */
 
diff -Nru a/include/linux/irq_cpustat.h b/include/linux/irq_cpustat.h
--- a/include/linux/irq_cpustat.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/irq_cpustat.h	Thu Aug  1 01:08:13 2002
@@ -24,7 +24,7 @@
 #define __IRQ_STAT(cpu, member)	(irq_stat[cpu].member)
 #else
 #define __IRQ_STAT(cpu, member)	((void)(cpu), irq_stat[0].member)
-#endif	
+#endif
 #endif
 
   /* arch independent irq_stat fields */
@@ -33,5 +33,12 @@
 #define ksoftirqd_task(cpu)	__IRQ_STAT((cpu), __ksoftirqd_task)
   /* arch dependent irq_stat fields */
 #define nmi_count(cpu)		__IRQ_STAT((cpu), __nmi_count)		/* i386, ia64 */
+
+#define local_hardirq_trylock()	hardirq_trylock(smp_processor_id())
+#define local_hardirq_endlock()	hardirq_trylock(smp_processor_id())
+#define local_irq_enter(irq)	irq_enter(smp_processor_id(), (irq))
+#define local_irq_exit(irq)	irq_exit(smp_processor_id(), (irq))
+#define local_softirq_pending()	softirq_pending(smp_processor_id())
+#define local_ksoftirqd_task()	ksoftirqd_task(smp_processor_id())
 
 #endif	/* __irq_cpustat_h */
diff -Nru a/include/linux/jffs2.h b/include/linux/jffs2.h
--- a/include/linux/jffs2.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/jffs2.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/linux/jffs2_fs_sb.h	Thu Aug  1 01:08:12 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/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	Thu Aug  1 01:08:12 2002
+++ b/include/linux/kernel.h	Thu Aug  1 01:08:12 2002
@@ -37,6 +37,13 @@
 #define	KERN_INFO	"<6>"	/* informational			*/
 #define	KERN_DEBUG	"<7>"	/* debug-level messages			*/
 
+extern int console_printk[];
+
+#define console_loglevel (console_printk[0])
+#define default_message_loglevel (console_printk[1])
+#define minimum_console_loglevel (console_printk[2])
+#define default_console_loglevel (console_printk[3])
+
 struct completion;
 
 extern struct notifier_block *panic_notifier_list;
@@ -72,8 +79,6 @@
 
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
-
-extern int console_loglevel;
 
 static inline void console_silent(void)
 {
diff -Nru a/include/linux/list.h b/include/linux/list.h
--- a/include/linux/list.h	Thu Aug  1 01:08:12 2002
+++ b/include/linux/list.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/linux/mm.h	Thu Aug  1 01:08:12 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 {
@@ -181,6 +182,36 @@
 };
 
 /*
+ * inlines for acquisition and release of PG_chainlock
+ */
+static inline void pte_chain_lock(struct page *page)
+{
+	/*
+	 * Assuming the lock is uncontended, this never enters
+	 * the body of the outer loop. If it is contended, then
+	 * within the inner loop a non-atomic test is used to
+	 * busywait with less bus contention for a good time to
+	 * 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();
+}
+
+/*
  * Methods to modify the page usage count.
  *
  * What counts for a page usage:
@@ -327,7 +358,6 @@
 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);
@@ -430,7 +460,7 @@
 	return ret;
 }
 
-extern int do_munmap(struct mm_struct *, unsigned long, size_t);
+extern int do_munmap(struct mm_struct *, unsigned long, size_t, int);
 
 extern unsigned long do_brk(unsigned long, unsigned long);
 
@@ -472,31 +502,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 01:08:12 2002
+++ b/include/linux/mman.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/linux/mmzone.h	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/include/linux/n_r3964.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/linux/nfs_fs.h	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/include/linux/nfs_fs_sb.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/linux/nfs_xdr.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/linux/page-flags.h	Thu Aug  1 01:08:12 2002
@@ -42,6 +42,10 @@
  * address space...
  */
 
+#include <linux/preempt.h>
+
+struct page;
+
 /*
  * Don't use the *_dontuse flags.  Use the macros.  Otherwise you'll break
  * locked- and dirty-page accounting.  The top eight bits of page->flags are
@@ -79,8 +83,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);
@@ -227,32 +230,6 @@
 #define TestSetPageDirect(page)	test_and_set_bit(PG_direct, &(page)->flags)
 #define ClearPageDirect(page)		clear_bit(PG_direct, &(page)->flags)
 #define TestClearPageDirect(page)	test_and_clear_bit(PG_direct, &(page)->flags)
-
-/*
- * inlines for acquisition and release of PG_chainlock
- */
-static inline void pte_chain_lock(struct page *page)
-{
-	/*
-	 * Assuming the lock is uncontended, this never enters
-	 * the body of the outer loop. If it is contended, then
-	 * within the inner loop a non-atomic test is used to
-	 * busywait with less bus contention for a good time to
-	 * attempt to acquire the lock bit.
-	 */
-	preempt_disable();
-	while (test_and_set_bit(PG_chainlock, &page->flags)) {
-		while (test_bit(PG_chainlock, &page->flags))
-			cpu_relax();
-	}
-}
-
-static inline void pte_chain_unlock(struct page *page)
-{
-	smp_mb__before_clear_bit();
-	clear_bit(PG_chainlock, &page->flags);
-	preempt_enable();
-}
 
 /*
  * The PageSwapCache predicate doesn't use a PG_flag at this time,
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/pci.h	Thu Aug  1 01:08:13 2002
@@ -567,6 +567,8 @@
 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;
+
 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 01:08:13 2002
+++ b/include/linux/pci_ids.h	Thu Aug  1 01:08:13 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/percpu.h b/include/linux/percpu.h
--- a/include/linux/percpu.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/percpu.h	Thu Aug  1 01:08:13 2002
@@ -2,11 +2,11 @@
 #define __LINUX_PERCPU_H
 #include <linux/config.h>
 
-#ifdef CONFIG_SMP
 #define __per_cpu_data	__attribute__((section(".data.percpu")))
+
+#ifdef CONFIG_SMP
 #include <asm/percpu.h>
 #else
-#define __per_cpu_data
 #define per_cpu(var, cpu)			var
 #define this_cpu(var)				var
 #endif
diff -Nru a/include/linux/rwsem-spinlock.h b/include/linux/rwsem-spinlock.h
--- a/include/linux/rwsem-spinlock.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/rwsem-spinlock.h	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/include/linux/rwsem.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/linux/sched.h	Thu Aug  1 01:08:12 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
  */
@@ -429,14 +429,14 @@
 
 #ifndef INIT_THREAD_SIZE
 # define INIT_THREAD_SIZE	2048*sizeof(long)
-#endif
-
 union thread_union {
 	struct thread_info thread_info;
 	unsigned long stack[INIT_THREAD_SIZE/sizeof(long)];
 };
 
 extern union thread_union init_thread_union;
+#endif
+
 extern struct task_struct init_task;
 
 extern struct   mm_struct init_mm;
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	Thu Aug  1 01:08:12 2002
+++ b/include/linux/security.h	Thu Aug  1 01:08:12 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/smp.h b/include/linux/smp.h
--- a/include/linux/smp.h	Thu Aug  1 01:08:13 2002
+++ b/include/linux/smp.h	Thu Aug  1 01:08:13 2002
@@ -57,10 +57,6 @@
  */
 extern int smp_threads_ready;
 
-extern volatile unsigned long smp_msg_data;
-extern volatile int smp_src_cpu;
-extern volatile int smp_msg_id;
-
 #define MSG_ALL_BUT_SELF	0x8000	/* Assume <32768 CPU's */
 #define MSG_ALL			0x8001
 
@@ -96,14 +92,6 @@
 #define cpu_online_map				1
 #define cpu_online(cpu)				({ cpu; 1; })
 #define num_online_cpus()			1
-#define __per_cpu_data
-#define per_cpu(var, cpu)			var
-#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)
-
 #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 01:08:12 2002
+++ b/include/linux/swap.h	Thu Aug  1 01:08:12 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 01:08:12 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 01:08:12 2002
+++ b/include/linux/sysctl.h	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/include/linux/timer.h	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/init/do_mounts.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/init/main.c	Thu Aug  1 01:08:12 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 migration_init(void);
+	extern int spawn_ksoftirqd(void);
+
+#if CONFIG_SMP
+	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 01:08:13 2002
+++ b/ipc/shm.c	Thu Aug  1 01:08:13 2002
@@ -671,7 +671,7 @@
 		shmdnext = shmd->vm_next;
 		if (shmd->vm_ops == &shm_vm_ops
 		    && shmd->vm_start - (shmd->vm_pgoff << PAGE_SHIFT) == (ulong) shmaddr) {
-			do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start);
+			do_munmap(mm, shmd->vm_start, shmd->vm_end - shmd->vm_start, 1);
 			retval = 0;
 		}
 	}
diff -Nru a/kernel/exec_domain.c b/kernel/exec_domain.c
--- a/kernel/exec_domain.c	Thu Aug  1 01:08:13 2002
+++ b/kernel/exec_domain.c	Thu Aug  1 01:08:13 2002
@@ -196,8 +196,10 @@
 
 	put_exec_domain(oep);
 
+#if 0
 	printk(KERN_DEBUG "[%s:%d]: set personality to %lx\n",
 			current->comm, current->pid, personality);
+#endif
 	return 0;
 }
 
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	Thu Aug  1 01:08:12 2002
+++ b/kernel/fork.c	Thu Aug  1 01:08:12 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>
 
@@ -99,7 +100,11 @@
 	init_task.rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
 }
 
-static struct task_struct *dup_task_struct(struct task_struct *orig)
+#if 1
+extern struct task_struct *dup_task_struct (struct task_struct *orig);
+#else
+
+struct task_struct *dup_task_struct(struct task_struct *orig)
 {
 	struct task_struct *tsk;
 	struct thread_info *ti;
@@ -128,6 +133,8 @@
 	kmem_cache_free(task_struct_cachep,tsk);
 }
 
+#endif
+
 /* Protects next_safe and last_pid. */
 spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
 
@@ -181,6 +188,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 +216,17 @@
 		retval = -ENOMEM;
 		if(mpnt->vm_flags & VM_DONTCOPY)
 			continue;
+
+		/*
+		 * FIXME: shared writable map accounting should be one off
+		 */
+		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 +267,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;
diff -Nru a/kernel/ksyms.c b/kernel/ksyms.c
--- a/kernel/ksyms.c	Thu Aug  1 01:08:12 2002
+++ b/kernel/ksyms.c	Thu Aug  1 01:08:12 2002
@@ -218,6 +218,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 +341,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);
@@ -384,7 +386,9 @@
 EXPORT_SYMBOL(del_timer);
 EXPORT_SYMBOL(request_irq);
 EXPORT_SYMBOL(free_irq);
+#if !defined(CONFIG_IA64)
 EXPORT_SYMBOL(irq_stat);
+#endif
 
 /* waitqueue handling */
 EXPORT_SYMBOL(add_wait_queue);
@@ -593,7 +597,9 @@
 /* init task, for moving kthread roots - ought to export a function ?? */
 
 EXPORT_SYMBOL(init_task);
+#ifndef CONFIG_IA64
 EXPORT_SYMBOL(init_thread_union);
+#endif
 
 EXPORT_SYMBOL(tasklist_lock);
 EXPORT_SYMBOL(pidhash);
diff -Nru a/kernel/printk.c b/kernel/printk.c
--- a/kernel/printk.c	Thu Aug  1 01:08:13 2002
+++ b/kernel/printk.c	Thu Aug  1 01:08:13 2002
@@ -16,6 +16,7 @@
  *	01Mar01 Andrew Morton <andrewm@uow.edu.au>
  */
 
+#include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
@@ -54,11 +55,12 @@
 
 DECLARE_WAIT_QUEUE_HEAD(log_wait);
 
-/* Keep together for sysctl support */
-int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
-int default_message_loglevel = DEFAULT_MESSAGE_LOGLEVEL;
-int minimum_console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
-int default_console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
+int console_printk[4] = {
+	DEFAULT_CONSOLE_LOGLEVEL,	/* console_loglevel */
+	DEFAULT_MESSAGE_LOGLEVEL,	/* default_message_loglevel */
+	MINIMUM_CONSOLE_LOGLEVEL,	/* minimum_console_loglevel */
+	DEFAULT_CONSOLE_LOGLEVEL,	/* default_console_loglevel */
+};
 
 int oops_in_progress;
 
@@ -325,6 +327,12 @@
 			__call_console_drivers(start, end);
 		}
 	}
+#ifdef CONFIG_IA64_EARLY_PRINTK
+	if (!console_drivers) {
+		static void early_printk (const char *str, size_t len);
+		early_printk(&LOG_BUF(start), end - start);
+	}
+#endif
 }
 
 /*
@@ -691,3 +699,50 @@
 		tty->driver.write(tty, 0, msg, strlen(msg));
 	return;
 }
+
+#ifdef CONFIG_IA64_EARLY_PRINTK
+
+#include <asm/io.h>
+
+#define VGABASE		((char *)0xc0000000000b8000)
+#define VGALINES	24
+#define VGACOLS		80
+
+static int current_ypos = VGALINES, current_xpos = 0;
+
+void
+early_printk (const char *str, size_t len)
+{
+	char c;
+	int  i, k, j;
+
+	while (len-- > 0) {
+		c = *str++;
+		if (current_ypos >= VGALINES) {
+			/* scroll 1 line up */
+			for (k = 1, j = 0; k < VGALINES; k++, j++) {
+				for (i = 0; i < VGACOLS; i++) {
+					writew(readw(VGABASE + 2*(VGACOLS*k + i)),
+					       VGABASE + 2*(VGACOLS*j + i));
+				}
+			}
+			for (i = 0; i < VGACOLS; i++) {
+				writew(0x720, VGABASE + 2*(VGACOLS*j + i));
+			}
+			current_ypos = VGALINES-1;
+		}
+		if (c == '\n') {
+			current_xpos = 0;
+			current_ypos++;
+		} else if (c != '\r')  {
+			writew(((0x7 << 8) | (unsigned short) c),
+			       VGABASE + 2*(VGACOLS*current_ypos + current_xpos++));
+			if (current_xpos >= VGACOLS) {
+				current_xpos = 0;
+				current_ypos++;
+			}
+		}
+	}
+}
+
+#endif /* CONFIG_IA64_EARLY_PRINTK */
diff -Nru a/kernel/ptrace.c b/kernel/ptrace.c
--- a/kernel/ptrace.c	Thu Aug  1 01:08:13 2002
+++ b/kernel/ptrace.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/kernel/sched.c	Thu Aug  1 01:08:12 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 };
+	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 01:08:12 2002
+++ b/kernel/softirq.c	Thu Aug  1 01:08:12 2002
@@ -38,7 +38,10 @@
    - Bottom halves: globally serialized, grr...
  */
 
+/* No separate irq_stat for ia64, it is part of PSA */
+#if !defined(CONFIG_IA64)
 irq_cpustat_t irq_stat[NR_CPUS];
+#endif /* CONFIG_IA64 */
 
 static struct softirq_action softirq_vec[32] __cacheline_aligned_in_smp;
 
@@ -69,7 +72,7 @@
 	local_irq_save(flags);
 	cpu = smp_processor_id();
 
-	pending = softirq_pending(cpu);
+	pending = local_softirq_pending();
 
 	if (pending) {
 		struct softirq_action *h;
@@ -78,7 +81,7 @@
 		local_bh_disable();
 restart:
 		/* Reset the pending bitmask before enabling irqs */
-		softirq_pending(cpu) = 0;
+		local_softirq_pending() = 0;
 
 		local_irq_enable();
 
@@ -93,7 +96,7 @@
 
 		local_irq_disable();
 
-		pending = softirq_pending(cpu);
+		pending = local_softirq_pending();
 		if (pending & mask) {
 			mask &= ~pending;
 			goto restart;
@@ -101,7 +104,7 @@
 		__local_bh_enable();
 
 		if (pending)
-			wakeup_softirqd(cpu);
+			wakeup_softirqd(smp_processor_id());
 	}
 
 	local_irq_restore(flags);
@@ -371,15 +374,15 @@
 	__set_current_state(TASK_INTERRUPTIBLE);
 	mb();
 
-	ksoftirqd_task(cpu) = current;
+	local_ksoftirqd_task() = current;
 
 	for (;;) {
-		if (!softirq_pending(cpu))
+		if (!local_softirq_pending())
 			schedule();
 
 		__set_current_state(TASK_RUNNING);
 
-		while (softirq_pending(cpu)) {
+		while (local_softirq_pending()) {
 			do_softirq();
 			cond_resched();
 		}
@@ -410,11 +413,11 @@
 
 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());
+#if CONFIG_SMP
 	register_cpu_notifier(&cpu_nfb);
+#endif
 	return 0;
 }
-
-__initcall(spawn_ksoftirqd);
diff -Nru a/kernel/suspend.c b/kernel/suspend.c
--- a/kernel/suspend.c	Thu Aug  1 01:08:12 2002
+++ b/kernel/suspend.c	Thu Aug  1 01:08:12 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>
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	Thu Aug  1 01:08:12 2002
+++ b/kernel/sysctl.c	Thu Aug  1 01:08:12 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;
@@ -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/timer.c b/kernel/timer.c
--- a/kernel/timer.c	Thu Aug  1 01:08:12 2002
+++ b/kernel/timer.c	Thu Aug  1 01:08:12 2002
@@ -886,7 +886,7 @@
 	if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 || t.tv_sec < 0)
 		return -EINVAL;
 
-
+#if !defined(__ia64__)
 	if (t.tv_sec == 0 && t.tv_nsec <= 2000000L &&
 	    current->policy != SCHED_NORMAL)
 	{
@@ -899,6 +899,7 @@
 		udelay((t.tv_nsec + 999) / 1000);
 		return 0;
 	}
+#endif
 
 	expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
 
diff -Nru a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
--- a/lib/rwsem-spinlock.c	Thu Aug  1 01:08:12 2002
+++ b/lib/rwsem-spinlock.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/lib/rwsem.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/mm/bootmem.c	Thu Aug  1 01:08:12 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);
@@ -144,6 +143,7 @@
 static void * __init __alloc_bootmem_core (bootmem_data_t *bdata, 
 	unsigned long size, unsigned long align, unsigned long goal)
 {
+	static unsigned long last_success;
 	unsigned long i, start = 0;
 	void *ret;
 	unsigned long offset, remaining_size;
@@ -169,6 +169,9 @@
 	if (goal && (goal >= bdata->node_boot_start) && 
 			((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) {
 		preferred = goal - bdata->node_boot_start;
+
+		if (last_success >= preferred)
+			preferred = last_success;
 	} else
 		preferred = 0;
 
@@ -180,6 +183,8 @@
 restart_scan:
 	for (i = preferred; i < eidx; i += incr) {
 		unsigned long j;
+		i = find_next_zero_bit((char *)bdata->node_bootmem_map, eidx, i);
+		i = (i + incr - 1) & -incr;
 		if (test_bit(i, bdata->node_bootmem_map))
 			continue;
 		for (j = i + 1; j < i + areasize; ++j) {
@@ -198,6 +203,7 @@
 	}
 	return NULL;
 found:
+	last_success = start << PAGE_SHIFT;
 	if (start >= eidx)
 		BUG();
 
@@ -257,21 +263,21 @@
 	map = bdata->node_bootmem_map;
 	for (i = 0; i < idx; ) {
 		unsigned long v = ~map[i / BITS_PER_LONG];
-		if (v) { 
+		if (v) {
 			unsigned long m;
-			for (m = 1; m && i < idx; m<<=1, page++, i++) { 
+			for (m = 1; m && i < idx; m<<=1, page++, i++) {
 				if (v & m) {
-			count++;
-			ClearPageReserved(page);
-			set_page_count(page, 1);
-			__free_page(page);
-		}
-	}
+					count++;
+					ClearPageReserved(page);
+					set_page_count(page, 1);
+					__free_page(page);
+				}
+			}
 		} else {
 			i+=BITS_PER_LONG;
-			page+=BITS_PER_LONG; 
-		} 	
-	}	
+			page+=BITS_PER_LONG;
+		}
+	}
 	total += count;
 
 	/*
@@ -339,12 +345,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 01:08:12 2002
+++ b/mm/filemap.c	Thu Aug  1 01:08:13 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
@@ -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 01:08:13 2002
+++ b/mm/memory.c	Thu Aug  1 01:08:13 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>
@@ -111,7 +110,7 @@
 	pmd = pmd_offset(dir, 0);
 	pgd_clear(dir);
 	for (j = 0; j < PTRS_PER_PMD ; j++) {
-		prefetchw(pmd+j+(PREFETCH_STRIDE/16));
+		prefetchw(pmd + j + PREFETCH_STRIDE/sizeof(*pmd));
 		free_one_pmd(tlb, pmd+j);
 	}
 	pmd_free_tlb(tlb, pmd);
@@ -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++;
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	Thu Aug  1 01:08:12 2002
+++ b/mm/mmap.c	Thu Aug  1 01:08:12 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,91 @@
 	__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;
 
-	return free > pages;
+	if (atomic_read(&vm_committed_space) < allowed)
+		return 1;
+
+	vm_unacct_memory(pages);
+
+	return 0;
+}
+
+void vm_unacct_vma(struct vm_area_struct *vma)
+{
+	int len = vma->vm_end - vma->vm_start;
+	if (vma->vm_flags & VM_ACCOUNT)
+		vm_unacct_memory(len >> PAGE_SHIFT);
 }
 
 /* Remove one vm structure from the inode's i_mapping address space. */
@@ -163,7 +204,7 @@
 
 	/* Always allow shrinking brk. */
 	if (brk <= mm->brk) {
-		if (!do_munmap(mm, newbrk, oldbrk-newbrk))
+		if (!do_munmap(mm, newbrk, oldbrk-newbrk, 1))
 			goto set_brk;
 		goto out;
 	}
@@ -177,10 +218,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 +423,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 +433,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;
@@ -485,7 +524,7 @@
 munmap_back:
 	vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
 	if (vma && vma->vm_start < addr + len) {
-		if (do_munmap(mm, addr, len))
+		if (do_munmap(mm, addr, len, 1))
 			return -ENOMEM;
 		goto munmap_back;
 	}
@@ -495,11 +534,17 @@
 	    > current->rlim[RLIMIT_AS].rlim_cur)
 		return -ENOMEM;
 
+	if (sysctl_overcommit_memory > 1)
+		vm_flags &= ~MAP_NORESERVE;
+
 	/* 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 ((((vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) ||
+			(file == NULL)) && !(flags & MAP_NORESERVE)) {
+		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 +556,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;
@@ -575,6 +621,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 +753,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 +917,6 @@
 	kmem_cache_free(vm_area_cachep, area);
 }
 
-
 /*
  * Update the VMA and inode share lists.
  *
@@ -856,19 +943,25 @@
 	struct vm_area_struct *mpnt,
 	struct vm_area_struct *prev,
 	unsigned long start,
-	unsigned long end)
+	unsigned long end,
+	int acct)
 {
 	mmu_gather_t *tlb;
 
 	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 (acct && (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);
@@ -946,7 +1039,7 @@
  * work.  This now handles partial unmappings.
  * Jeremy Fitzhardine <jeremy@sw.oz.au>
  */
-int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
+int do_munmap(struct mm_struct *mm, unsigned long start, size_t len, int acct)
 {
 	unsigned long end;
 	struct vm_area_struct *mpnt, *prev, *last;
@@ -990,7 +1083,7 @@
 	 */
 	spin_lock(&mm->page_table_lock);
 	mpnt = touched_by_munmap(mm, mpnt, prev, end);
-	unmap_region(mm, mpnt, prev, start, end);
+	unmap_region(mm, mpnt, prev, start, end, acct);
 	spin_unlock(&mm->page_table_lock);
 
 	/* Fix up all other VM information */
@@ -1005,7 +1098,7 @@
 	struct mm_struct *mm = current->mm;
 
 	down_write(&mm->mmap_sem);
-	ret = do_munmap(mm, addr, len);
+	ret = do_munmap(mm, addr, len, 1);
 	up_write(&mm->mmap_sem);
 	return ret;
 }
@@ -1042,7 +1135,7 @@
  munmap_back:
 	vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
 	if (vma && vma->vm_start < addr + len) {
-		if (do_munmap(mm, addr, len))
+		if (do_munmap(mm, addr, len, 1))
 			return -ENOMEM;
 		goto munmap_back;
 	}
@@ -1058,7 +1151,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 +1161,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 +1219,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_vma(mpnt);
 
 		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 01:08:13 2002
+++ b/mm/mprotect.c	Thu Aug  1 01:08:13 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,6 +251,7 @@
 {
 	pgprot_t newprot;
 	int error;
+	unsigned long charged = 0;
 
 	if (newflags == vma->vm_flags) {
 		*pprev = vma;
@@ -264,9 +268,18 @@
 	else
 		error = mprotect_fixup_middle(vma, pprev, start, end, newflags, newprot);
 
-	if (error)
+	if (error) {
+		if (newflags & PROT_WRITE)
+			vm_unacct_memory(charged);
 		return error;
+	}
 
+	/*
+	 * Delayed accounting for reduction of memory use - done last to
+	 * avoid allocation races
+	 */
+	if (charged && !(newflags & PROT_WRITE))
+		vm_unacct_memory(charged);
 	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 01:08:13 2002
+++ b/mm/mremap.c	Thu Aug  1 01:08:13 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;
@@ -209,7 +210,11 @@
 				new_vma->vm_ops->open(new_vma);
 			insert_vm_struct(current->mm, new_vma);
 		}
-		do_munmap(current->mm, addr, old_len);
+		/*
+		 * The old VMA has been accounted for,
+		 * don't double account
+		 */
+		do_munmap(current->mm, addr, old_len, 0);
 		current->mm->total_vm += new_len >> PAGE_SHIFT;
 		if (new_vma->vm_flags & VM_LOCKED) {
 			current->mm->locked_vm += new_len >> PAGE_SHIFT;
@@ -224,6 +229,8 @@
 	return -ENOMEM;
 }
 
+extern int sysctl_overcommit_memory;	/* FIXME!! */
+
 /*
  * Expand (or shrink) an existing mapping, potentially moving it at the
  * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
@@ -237,6 +244,7 @@
 {
 	struct vm_area_struct *vma;
 	unsigned long ret = -EINVAL;
+	unsigned long charged = 0;
 
 	if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
 		goto out;
@@ -266,16 +274,17 @@
 		if ((addr <= new_addr) && (addr+old_len) > new_addr)
 			goto out;
 
-		do_munmap(current->mm, new_addr, new_len);
+		do_munmap(current->mm, new_addr, new_len, 1);
 	}
 
 	/*
 	 * 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);
+		do_munmap(current->mm, addr+new_len, old_len - new_len, 1);
 		if (!(flags & MREMAP_FIXED) || (new_addr == addr))
 			goto out;
 	}
@@ -305,11 +314,14 @@
 	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 (sysctl_overcommit_memory > 1)
+		flags &= ~MAP_NORESERVE;
+	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 +368,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 01:08:12 2002
+++ b/mm/numa.c	Thu Aug  1 01:08:12 2002
@@ -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 01:08:12 2002
+++ b/mm/oom_kill.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/mm/page_alloc.c	Thu Aug  1 01:08:12 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/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	Thu Aug  1 01:08:13 2002
+++ b/mm/rmap.c	Thu Aug  1 01:08:13 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);
 }
 
 /**
@@ -205,12 +208,14 @@
 	}
 	printk("\n");
 	printk(KERN_ERR "page_remove_rmap: driver cleared PG_reserved ?\n");
+#else
+	BUG();
 #endif
 
 out:
+	dec_page_state(nr_reverse_maps);
 	pte_chain_unlock(page);
 	return;
-			
 }
 
 /**
@@ -355,27 +360,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 +375,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 +390,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 01:08:13 2002
+++ b/mm/shmem.c	Thu Aug  1 01:08:13 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>
@@ -358,10 +360,41 @@
 	up(&info->sem);
 }
 
+static int shmem_notify_change(struct dentry * dentry, struct iattr *attr)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	if (attr->ia_valid & ATTR_SIZE) {
+		/*
+	 	 * Account swap file usage based on new file size	
+	 	 */
+		long change;
+
+		change = ((attr->ia_size + PAGE_SIZE - 1) >> PAGE_SHIFT) -
+			((inode->i_size + PAGE_SIZE - 1 ) >> PAGE_SHIFT);
+
+		if (attr->ia_size > inode->i_size) {
+			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);
+
+	return error;
+}
+
+
 static void shmem_delete_inode(struct inode * inode)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
 
+	vm_unacct_memory((inode->i_size) >> PAGE_SHIFT);
+
 	inode->i_size = 0;
 	if (inode->i_op->truncate == shmem_truncate){ 
 		spin_lock (&shmem_ilock);
@@ -824,6 +857,7 @@
 	unsigned long	written;
 	long		status;
 	int		err;
+	loff_t		maxpos;
 
 	if ((ssize_t) count < 0)
 		return -EINVAL;
@@ -836,12 +870,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 +883,15 @@
 	if (file->f_flags & O_APPEND)
 		pos = inode->i_size;
 
+	maxpos = inode->i_size;
+	if (pos + count > inode->i_size) {
+		maxpos = pos + count;
+		if (!vm_enough_memory((maxpos - inode->i_size) >> PAGE_SHIFT)) {
+			err = -ENOMEM;
+			goto out_nc;
+		}
+	}
+
 	/*
 	 * Check whether we've reached the file size limit.
 	 */
@@ -938,6 +981,10 @@
 
 	err = written ? written : status;
 out:
+	/* Short writes give back address space */
+	if (inode->i_size != maxpos)
+		vm_unacct_memory((maxpos - inode->i_size) >> PAGE_SHIFT);
+out_nc:
 	up(&inode->i_sem);
 	return err;
 fail_write:
@@ -1477,6 +1524,7 @@
 
 static struct inode_operations shmem_inode_operations = {
 	truncate:	shmem_truncate,
+	setattr:	shmem_notify_change,
 };
 
 static struct inode_operations shmem_dir_inode_operations = {
@@ -1600,12 +1648,11 @@
  */
 struct file *shmem_file_setup(char * name, loff_t size)
 {
-	int error;
+	int error = -ENOMEM;
 	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)
 		return ERR_PTR(-EINVAL);
@@ -1619,7 +1666,7 @@
 	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();
@@ -1645,6 +1692,8 @@
 	put_filp(file);
 put_dentry:
 	dput (dentry);
+put_memory:
+	vm_unacct_memory((size) >> PAGE_CACHE_SHIFT);
 	return ERR_PTR(error);	
 }
 /*
diff -Nru a/mm/swap.c b/mm/swap.c
--- a/mm/swap.c	Thu Aug  1 01:08:13 2002
+++ b/mm/swap.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/mm/swap_state.c	Thu Aug  1 01:08:13 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>
@@ -42,8 +41,7 @@
 	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 01:08:12 2002
+++ b/mm/swapfile.c	Thu Aug  1 01:08:12 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 01:08:12 2002
+++ b/mm/vmscan.c	Thu Aug  1 01:08:12 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/Config.in b/net/Config.in
--- a/net/Config.in	Thu Aug  1 01:08:12 2002
+++ b/net/Config.in	Thu Aug  1 01:08:12 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 01:08:13 2002
+++ b/net/Makefile	Thu Aug  1 01:08:13 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/khttpd/Config.help b/net/khttpd/Config.help
--- a/net/khttpd/Config.help	Thu Aug  1 01:08:13 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 01:08:13 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 01:08:13 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 01:08:13 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 01:08:12 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 01:08:12 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 01:08:12 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 01:08:12 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 01:08:12 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 01:08:13 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 01:08:13 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 01:08:13 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 01:08:12 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 01:08:12 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 01:08:12 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 01:08:12 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 01:08:12 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 01:08:13 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 01:08:12 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 01:08:12 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 01:08:12 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/netsyms.c b/net/netsyms.c
--- a/net/netsyms.c	Thu Aug  1 01:08:13 2002
+++ b/net/netsyms.c	Thu Aug  1 01:08:13 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/sound/core/info.c b/sound/core/info.c
--- a/sound/core/info.c	Thu Aug  1 01:08:13 2002
+++ b/sound/core/info.c	Thu Aug  1 01:08:13 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/sound.c b/sound/core/sound.c
--- a/sound/core/sound.c	Thu Aug  1 01:08:12 2002
+++ b/sound/core/sound.c	Thu Aug  1 01:08:12 2002
@@ -368,10 +368,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
 	
diff -Nru a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c
--- a/sound/oss/cs4281/cs4281m.c	Thu Aug  1 01:08:13 2002
+++ b/sound/oss/cs4281/cs4281m.c	Thu Aug  1 01:08:13 2002
@@ -1942,8 +1942,8 @@
 		len -= x;
 	}
 	CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO
-		"cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n",
-			(unsigned)c, (unsigned)((char *) buf) + bptr, len));
+		"cs4281: clear_advance(): memset %d at %p for %d size \n",
+			(unsigned)c, ((char *) buf) + bptr, len));
 	memset(((char *) buf) + bptr, c, len);
 }
 
@@ -1978,9 +1978,8 @@
 				wake_up(&s->dma_adc.wait);
 		}
 		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
-			"cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
-				(unsigned)s, s->dma_adc.hwptr, 
-				s->dma_adc.total_bytes, s->dma_adc.count));
+			"cs4281: cs4281_update_ptr(): s=%p hwptr=%d total_bytes=%d count=%d \n",
+				s, s->dma_adc.hwptr, s->dma_adc.total_bytes, s->dma_adc.count));
 	}
 	// update DAC pointer 
 	//
@@ -2012,11 +2011,10 @@
 				// Continue to play silence until the _release.
 				//
 				CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO
-					"cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n",
+					"cs4281: cs4281_update_ptr(): memset %d at %p for %d size \n",
 						(unsigned)(s->prop_dac.fmt & 
 						(AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, 
-						(unsigned)s->dma_dac.rawbuf, 
-						s->dma_dac.dmasize));
+						s->dma_dac.rawbuf, s->dma_dac.dmasize));
 				memset(s->dma_dac.rawbuf,
 				       (s->prop_dac.
 					fmt & (AFMT_U8 | AFMT_U16_LE)) ?
@@ -2047,9 +2045,8 @@
 			}
 		}
 		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
-			"cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
-				(unsigned) s, s->dma_dac.hwptr, 
-				s->dma_dac.total_bytes, s->dma_dac.count));
+			"cs4281: cs4281_update_ptr(): s=%p hwptr=%d total_bytes=%d count=%d \n",
+				s, s->dma_dac.hwptr, s->dma_dac.total_bytes, s->dma_dac.count));
 	}
 }
 
@@ -2180,8 +2177,7 @@
 
 	VALIDATE_STATE(s);
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
-		 "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n",
-			 (unsigned) s, cmd));
+		 "cs4281: mixer_ioctl(): s=%p cmd=0x%.8x\n", s, cmd));
 #if CSDEBUG
 	cs_printioctl(cmd);
 #endif
@@ -2746,9 +2742,8 @@
 	CS_DBGOUT(CS_FUNCTION, 2,
 		  printk(KERN_INFO "cs4281: CopySamples()+ "));
 	CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
-		 " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n",
-			 (unsigned) dst, (unsigned) src, (unsigned) count,
-			 (unsigned) iChannels, (unsigned) fmt));
+		 " dst=%p src=%p count=%d iChannels=%d fmt=0x%x\n",
+			 dst, src, (unsigned) count, (unsigned) iChannels, (unsigned) fmt));
 
 	// Gershwin does format conversion in hardware so normally
 	// we don't do any host based coversion. The data formatter
@@ -2828,9 +2823,9 @@
 	void *src = hwsrc;	//default to the standard destination buffer addr
 
 	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO
-		"cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=0x%.8x\n",
+		"cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=%p\n",
 			s->prop_adc.fmt, s->prop_adc.fmt_original,
-			(unsigned) cnt, (unsigned) dest));
+			(unsigned) cnt, dest));
 
 	if (cnt > s->dma_adc.dmasize) {
 		cnt = s->dma_adc.dmasize;
@@ -2875,7 +2870,7 @@
 	unsigned copied = 0;
 
 	CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
-		  printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count));
+		  printk(KERN_INFO "cs4281: cs4281_read()+ %Zu \n", count));
 
 	VALIDATE_STATE(s);
 	if (ppos != &file->f_pos)
@@ -2898,7 +2893,7 @@
 //
 	while (count > 0) {
 		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
-			"_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n",
+			"_read() count>0 count=%Zu .count=%d .swptr=%d .hwptr=%d \n",
 				count, s->dma_adc.count,
 				s->dma_adc.swptr, s->dma_adc.hwptr));
 		spin_lock_irqsave(&s->lock, flags);
@@ -2955,11 +2950,10 @@
 		// the "cnt" is the number of bytes to read.
 
 		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO
-			"_read() copy_to cnt=%d count=%d ", cnt, count));
+			"_read() copy_to cnt=%d count=%Zu ", cnt, count));
 		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
-			 " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n",
-				 s->dma_adc.dmasize, s->dma_adc.count,
-				 (unsigned) buffer, ret));
+			 " .dmasize=%d .count=%d buffer=%p ret=%Zd\n",
+				 s->dma_adc.dmasize, s->dma_adc.count, buffer, ret));
 
 		if (cs_copy_to_user
 		    (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied))
@@ -2975,7 +2969,7 @@
 		start_adc(s);
 	}
 	CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
-		  printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret));
+		  printk(KERN_INFO "cs4281: cs4281_read()- %Zd\n", ret));
 	return ret;
 }
 
@@ -2991,7 +2985,7 @@
 	int cnt;
 
 	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
-		  printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n",
+		  printk(KERN_INFO "cs4281: cs4281_write()+ count=%Zu\n",
 			 count));
 	VALIDATE_STATE(s);
 
@@ -3047,7 +3041,7 @@
 		start_dac(s);
 	}
 	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
-		  printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret));
+		  printk(KERN_INFO "cs4281: cs4281_write()- %Zd\n", ret));
 	return ret;
 }
 
@@ -3168,8 +3162,7 @@
 	int val, mapped, ret;
 
 	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
-		 "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n",
-			 (unsigned) file, cmd));
+		 "cs4281: cs4281_ioctl(): file=%p cmd=0x%.8x\n", file, cmd));
 #if CSDEBUG
 	cs_printioctl(cmd);
 #endif
@@ -3205,7 +3198,7 @@
 			 "cs4281: cs4281_ioctl(): DSP_RESET\n"));
 		if (file->f_mode & FMODE_WRITE) {
 			stop_dac(s);
-			synchronize_irq();
+			synchronize_irq(s->irq);
 			s->dma_dac.swptr = s->dma_dac.hwptr =
 			    s->dma_dac.count = s->dma_dac.total_bytes =
 			    s->dma_dac.blocks = s->dma_dac.wakeup = 0;
@@ -3213,7 +3206,7 @@
 		}
 		if (file->f_mode & FMODE_READ) {
 			stop_adc(s);
-			synchronize_irq();
+			synchronize_irq(s->irq);
 			s->dma_adc.swptr = s->dma_adc.hwptr =
 			    s->dma_adc.count = s->dma_adc.total_bytes =
 			    s->dma_adc.blocks = s->dma_dac.wakeup = 0;
@@ -3599,8 +3592,8 @@
 	    (struct cs4281_state *) file->private_data;
 
 	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk(KERN_INFO
-		 "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n",
-			 (unsigned) inode, (unsigned) file, file->f_mode));
+		 "cs4281: cs4281_release(): inode=%p file=%p f_mode=%d\n",
+			 inode, file, file->f_mode));
 
 	VALIDATE_STATE(s);
 
@@ -3634,8 +3627,8 @@
 	struct list_head *entry;
 
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
-		"cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n",
-			(unsigned) inode, (unsigned) file, file->f_mode));
+		"cs4281: cs4281_open(): inode=%p file=%p f_mode=0x%x\n",
+			inode, file, file->f_mode));
 
 	list_for_each(entry, &cs4281_devs)
 	{
@@ -4344,10 +4337,8 @@
 
 	CS_DBGOUT(CS_INIT, 2,
 		  printk(KERN_INFO
-			 "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n",
-			 (unsigned) temp1, (unsigned) temp2,
-			 (unsigned) s->pBA0, (unsigned) s->pBA1));
-
+			 "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=%p pBA1=%p \n",
+			 (unsigned) temp1, (unsigned) temp2, s->pBA0, s->pBA1));
 	CS_DBGOUT(CS_INIT, 2,
 		  printk(KERN_INFO
 			 "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n",
@@ -4394,15 +4385,13 @@
 	if (pmdev)
 	{
 		CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO
-			 "cs4281: probe() pm_register() succeeded (0x%x).\n",
-				(unsigned)pmdev));
+			 "cs4281: probe() pm_register() succeeded (%p).\n", pmdev));
 		pmdev->data = s;
 	}
 	else
 	{
 		CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 0, printk(KERN_INFO
-			 "cs4281: probe() pm_register() failed (0x%x).\n",
-				(unsigned)pmdev));
+			 "cs4281: probe() pm_register() failed (%p).\n", pmdev));
 		s->pm.flags |= CS4281_PM_NOT_REGISTERED;
 	}
 #endif
@@ -4452,7 +4441,7 @@
 {
 	struct cs4281_state *s = pci_get_drvdata(pci_dev);
 	// stop DMA controller 
-	synchronize_irq();
+	synchronize_irq(s->irq);
 	free_irq(s->irq, s);
 	unregister_sound_dsp(s->dev_audio);
 	unregister_sound_mixer(s->dev_mixer);
diff -Nru a/sound/oss/cs4281/cs4281pm-24.c b/sound/oss/cs4281/cs4281pm-24.c
--- a/sound/oss/cs4281/cs4281pm-24.c	Thu Aug  1 01:08:13 2002
+++ b/sound/oss/cs4281/cs4281pm-24.c	Thu Aug  1 01:08:13 2002
@@ -38,16 +38,16 @@
 #define CS4281_SUSPEND_TBL cs4281_suspend_tbl
 #define CS4281_RESUME_TBL cs4281_resume_tbl
 */
-#define CS4281_SUSPEND_TBL cs4281_null
-#define CS4281_RESUME_TBL cs4281_null
+#define CS4281_SUSPEND_TBL	(int (*) (struct pci_dev *, u32)) cs4281_null
+#define CS4281_RESUME_TBL	(int (*) (struct pci_dev *)) cs4281_null
 
 int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
 	struct cs4281_state *state;
 
 	CS_DBGOUT(CS_PM, 2, printk(KERN_INFO 
-		"cs4281: cs4281_pm_callback dev=0x%x rqst=0x%x state=%d\n",
-			(unsigned)dev,(unsigned)rqst,(unsigned)data));
+		"cs4281: cs4281_pm_callback dev=%p rqst=0x%x state=%p\n",
+			dev,(unsigned)rqst,data));
 	state = (struct cs4281_state *) dev->data;
 	if (state) {
 		switch(rqst) {
@@ -78,7 +78,7 @@
 }
 
 #else /* CS4281_PM */
-#define CS4281_SUSPEND_TBL cs4281_null
-#define CS4281_RESUME_TBL cs4281_null
+#define CS4281_SUSPEND_TBL	(int (*) (struct pci_dev *, u32)) cs4281_null
+#define CS4281_RESUME_TBL 	(int (*) (struct pci_dev *)) cs4281_null
 #endif /* CS4281_PM */
 
diff -Nru a/sound/oss/cs46xx.c b/sound/oss/cs46xx.c
--- a/sound/oss/cs46xx.c	Thu Aug  1 01:08:12 2002
+++ b/sound/oss/cs46xx.c	Thu Aug  1 01:08:12 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/soundcard.c b/sound/oss/soundcard.c
--- a/sound/oss/soundcard.c	Thu Aug  1 01:08:13 2002
+++ b/sound/oss/soundcard.c	Thu Aug  1 01:08:13 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 01:08:13 2002
+++ b/sound/oss/trident.c	Thu Aug  1 01:08:13 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 01:08:12 2002
+++ b/sound/oss/trident.h	Thu Aug  1 01:08:12 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 */
