## Automatically generated incremental diff
## From:   linux-2.4.21-rc6
## To:     linux-2.4.21-rc7
## Robot:  $Id: make-incremental-diff,v 1.11 2002/02/20 02:59:33 hpa Exp $

diff -urN linux-2.4.21-rc6/Makefile linux-2.4.21-rc7/Makefile
--- linux-2.4.21-rc6/Makefile	2003-06-03 10:03:30.000000000 -0700
+++ linux-2.4.21-rc7/Makefile	2003-06-03 10:03:54.000000000 -0700
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 21
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.21-rc6/arch/sh/kernel/io_7751se.c linux-2.4.21-rc7/arch/sh/kernel/io_7751se.c
--- linux-2.4.21-rc6/arch/sh/kernel/io_7751se.c	2002-02-25 11:37:56.000000000 -0800
+++ linux-2.4.21-rc7/arch/sh/kernel/io_7751se.c	2003-06-03 10:04:17.000000000 -0700
@@ -97,7 +97,7 @@
 #define CHECK_SH7751_PCIIO(port) \
   ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE)))
 #else
-#define CHECK_SH_7751_PCIIO(port) (0)
+#define CHECK_SH7751_PCIIO(port) (0)
 #endif
 
 /*
diff -urN linux-2.4.21-rc6/arch/sh/kernel/pcibios.c linux-2.4.21-rc7/arch/sh/kernel/pcibios.c
--- linux-2.4.21-rc6/arch/sh/kernel/pcibios.c	2002-11-28 15:53:11.000000000 -0800
+++ linux-2.4.21-rc7/arch/sh/kernel/pcibios.c	2003-06-03 10:04:17.000000000 -0700
@@ -73,7 +73,7 @@
 	}
 }
 
-int pcibios_enable_device(struct pci_dev *dev)
+int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	u16 cmd, old_cmd;
 	int idx;
@@ -82,6 +82,8 @@
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
 	old_cmd = cmd;
 	for(idx=0; idx<6; idx++) {
+		if (!(mask & (1 << idx)))
+			continue;
 		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);
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/auxio.c linux-2.4.21-rc7/arch/sparc/kernel/auxio.c
--- linux-2.4.21-rc6/arch/sparc/kernel/auxio.c	1999-12-20 22:05:52.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/auxio.c	2003-06-03 10:04:17.000000000 -0700
@@ -6,13 +6,19 @@
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/config.h>
+#include <linux/spinlock.h>
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/auxio.h>
 #include <asm/string.h>		/* memset(), Linux has no bzero() */
 
 /* Probe and map in the Auxiliary I/O register */
-unsigned char *auxio_register;
+
+/* auxio_register is not static because it is referenced 
+ * in entry.S::floppy_tdone
+ */
+unsigned long auxio_register = 0UL;
+static spinlock_t auxio_lock = SPIN_LOCK_UNLOCKED;
 
 void __init auxio_probe(void)
 {
@@ -23,7 +29,6 @@
 	switch (sparc_cpu_model) {
 	case sun4d:
 	case sun4:
-		auxio_register = 0;
 		return;
 	default:
 		break;
@@ -37,12 +42,10 @@
 		if(!auxio_nd) {
 #ifdef CONFIG_PCI
 			/* There may be auxio on Ebus */
-			auxio_register = 0;
 			return;
 #else
 			if(prom_searchsiblings(node, "leds")) {
 				/* VME chassis sun4m machine, no auxio exists. */
-				auxio_register = 0;
 				return;
 			}
 			prom_printf("Cannot find auxio node, cannot continue...\n");
@@ -56,14 +59,46 @@
 	r.flags = auxregs[0].which_io & 0xF;
 	r.start = auxregs[0].phys_addr;
 	r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1;
-	auxio_register = (unsigned char *) sbus_ioremap(&r, 0,
-	    auxregs[0].reg_size, "auxio");
+	auxio_register = sbus_ioremap(&r, 0, auxregs[0].reg_size, "auxio");
 	/* Fix the address on sun4m and sun4c. */
 	if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 ||
 	   sparc_cpu_model == sun4c)
-		auxio_register = (unsigned char *) ((int)auxio_register | 3);
+		auxio_register |= 3;
+
+	set_auxio(AUXIO_LED, 0);
+}
+
+unsigned char get_auxio(void)
+{
+	if(auxio_register) 
+		return sbus_readb(auxio_register);
+	return 0;
+}
 
-	TURN_ON_LED;
+void set_auxio(unsigned char bits_on, unsigned char bits_off)
+{
+	unsigned char regval;
+	unsigned long flags;
+	spin_lock_irqsave(&auxio_lock, flags);
+	switch(sparc_cpu_model) {
+	case sun4c:
+		regval = sbus_readb(auxio_register);
+		sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN,
+			auxio_register);
+		break;
+	case sun4m:
+		if(!auxio_register)
+			break;     /* VME chassic sun4m, no auxio. */
+		regval = sbus_readb(auxio_register);
+		sbus_writeb(((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M,
+			auxio_register);
+		break;
+	case sun4d:
+		break;
+	default:
+		panic("Can't set AUXIO register on this machine.");
+	};
+	spin_unlock_irqrestore(&auxio_lock, flags);
 }
 
 
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/entry.S linux-2.4.21-rc7/arch/sparc/kernel/entry.S
--- linux-2.4.21-rc6/arch/sparc/kernel/entry.S	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/entry.S	2003-06-03 10:04:17.000000000 -0700
@@ -38,6 +38,14 @@
 
 #define NR_SYSCALLS 256      /* Each OS is different... */
 
+/* These are just handy. */
+#define _SV	save	%sp, -STACKFRAME_SZ, %sp
+#define _RS     restore 
+
+#define FLUSH_ALL_KERNEL_WINDOWS \
+	_SV; _SV; _SV; _SV; _SV; _SV; _SV; \
+	_RS; _RS; _RS; _RS; _RS; _RS; _RS;
+
 /* First, KGDB low level things.  This is a rewrite
  * of the routines found in the sparc-stub.c asm() statement
  * from the gdb distribution.  This is also dual-purpose
@@ -70,11 +78,11 @@
 	/* Make sure kgdb sees the same state we just saved. */
 	LOAD_PT_GLOBALS(sp)
 	LOAD_PT_INS(sp)
-	ld	[%sp + REGWIN_SZ + PT_Y], %l4
-	ld	[%sp + REGWIN_SZ + PT_WIM], %l3
-	ld	[%sp + REGWIN_SZ + PT_PSR], %l0
-	ld	[%sp + REGWIN_SZ + PT_PC], %l1
-	ld	[%sp + REGWIN_SZ + PT_NPC], %l2
+	ld	[%sp + STACKFRAME_SZ + PT_Y], %l4
+	ld	[%sp + STACKFRAME_SZ + PT_WIM], %l3
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %l0
+	ld	[%sp + STACKFRAME_SZ + PT_PC], %l1
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l2
 	rd	%tbr, %l5	/* Never changes... */
 
 	/* Make kgdb exception frame. */	
@@ -94,7 +102,7 @@
 	WRITE_PAUSE
 
 	call	C_LABEL(handle_exception)
-	 add	%sp, REGWIN_SZ, %o0	! Pass address of registers
+	 add	%sp, STACKFRAME_SZ, %o0	! Pass address of registers
 
 	/* Load new kgdb register set. */
 	LOAD_KGDB_GLOBALS(sp)
@@ -263,7 +271,7 @@
 	mov	11, %o0			! floppy irq level (unused anyway)
 	mov	%g0, %o1		! devid is not used in fast interrupts
 	call	C_LABEL(sparc_floppy_irq)
-	 add	%sp, REGWIN_SZ, %o2	! struct pt_regs *regs
+	 add	%sp, STACKFRAME_SZ, %o2	! struct pt_regs *regs
 
 	RESTORE_ALL
 	
@@ -312,7 +320,7 @@
 	mov	%l7, %o0		! irq level
 patch_handler_irq:
 	call	C_LABEL(handler_irq)
-	 add	%sp, REGWIN_SZ, %o1	! pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
 	or	%l0, PSR_PIL, %g2	! restore PIL after handler_irq
 	wr	%g2, PSR_ET, %psr	! keep ET up
 	WRITE_PAUSE
@@ -329,7 +337,7 @@
 	wr	%g2, PSR_ET, %psr
 	WRITE_PAUSE
 	call	C_LABEL(smp4m_percpu_timer_interrupt)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 	RESTORE_ALL
@@ -436,7 +444,7 @@
 	wr	%g2, PSR_ET, %psr
 	WRITE_PAUSE
 	call	C_LABEL(smp4d_percpu_timer_interrupt)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 	RESTORE_ALL
@@ -498,7 +506,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_illegal_instruction)
@@ -518,7 +526,7 @@
 	wr	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_priv_instruction)
@@ -541,7 +549,7 @@
 
 	ld	[%l1], %o1
 	call	C_LABEL(kernel_unaligned_trap)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
 
@@ -553,7 +561,7 @@
 
 	ld	[%l1], %o1
 	call	C_LABEL(user_unaligned_trap)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
 
@@ -566,7 +574,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_fpd_trap)
@@ -605,7 +613,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(do_fpe_trap)
@@ -622,7 +630,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_tag_overflow)
@@ -639,7 +647,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_watchpoint)
@@ -656,7 +664,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_reg_access)
@@ -673,7 +681,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_cp_disabled)
@@ -690,7 +698,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_cp_exception)
@@ -707,7 +715,7 @@
 	wr	%l0, PSR_ET, %psr		! re-enable traps
 	WRITE_PAUSE
 
-	add	%sp, REGWIN_SZ, %o0
+	add	%sp, STACKFRAME_SZ, %o0
 	mov	%l1, %o1
 	mov	%l2, %o2
 	call	C_LABEL(handle_hw_divzero)
@@ -731,10 +739,10 @@
 	 nop
 
 	/* Advance over the trap instruction. */
-	ld	[%sp + REGWIN_SZ + PT_NPC], %l1
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1
 	add	%l1, 0x4, %l2
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
-	st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
+	st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 	RESTORE_ALL
 
@@ -746,10 +754,10 @@
 	FLUSH_ALL_KERNEL_WINDOWS
 
 	/* Advance over the trap instruction. */
-	ld	[%sp + REGWIN_SZ + PT_NPC], %l1
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1
 	add	%l1, 0x4, %l2
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
-	st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
+	st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 	RESTORE_ALL
 
@@ -818,7 +826,7 @@
 	sub	%o0, 0x4, %o0
 	lda	[%o0] ASI_CONTROL, %o3	! async error
 	call	C_LABEL(sparc_lvl15_nmi)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
 
@@ -1152,7 +1160,7 @@
 	WRITE_PAUSE
 
 	call	C_LABEL(do_sun4c_fault)
-	 add	%sp, REGWIN_SZ, %o0	! arg1 = pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o0	! arg1 = pt_regs ptr
 
 	RESTORE_ALL
 
@@ -1186,7 +1194,7 @@
 	WRITE_PAUSE
 
 	call	C_LABEL(do_sparc_fault)
-	 add	%sp, REGWIN_SZ, %o0	! arg1 = pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o0	! arg1 = pt_regs ptr
 
 	RESTORE_ALL
 
@@ -1224,7 +1232,7 @@
 	.globl	C_LABEL(sys_nis_syscall)
 C_LABEL(sys_nis_syscall):
 	mov	%o7, %l5
-	add	%sp, REGWIN_SZ, %o0		! pt_regs *regs arg
+	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
 	call	C_LABEL(c_sys_nis_syscall)
 	 mov	%l5, %o7
 
@@ -1232,7 +1240,7 @@
 	.globl	C_LABEL(sys_ptrace)
 C_LABEL(sys_ptrace):
 	call	C_LABEL(do_ptrace)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + AOFF_task_ptrace], %l5
 	andcc	%l5, 0x02, %g0
@@ -1249,7 +1257,7 @@
 	.globl	C_LABEL(sys_execve)
 C_LABEL(sys_execve):
 	mov	%o7, %l5
-	add	%sp, REGWIN_SZ, %o0		! pt_regs *regs arg
+	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
 	call	C_LABEL(sparc_execve)
 	 mov	%l5, %o7
 
@@ -1257,7 +1265,7 @@
 	.globl	C_LABEL(sys_pipe)
 C_LABEL(sys_pipe):
 	mov	%o7, %l5
-	add	%sp, REGWIN_SZ, %o0		! pt_regs *regs arg
+	add	%sp, STACKFRAME_SZ, %o0		! pt_regs *regs arg
 	call	C_LABEL(sparc_pipe)
 	 mov	%l5, %o7
 
@@ -1282,7 +1290,7 @@
 C_LABEL(sys_sigpause):
 	/* Note: %o0 already has correct value... */
 	call	C_LABEL(do_sigpause)
-	 add	%sp, REGWIN_SZ, %o1
+	 add	%sp, STACKFRAME_SZ, %o1
 
 	ld	[%curptr + AOFF_task_ptrace], %l5
 	andcc	%l5, 0x02, %g0
@@ -1300,7 +1308,7 @@
 	.globl	C_LABEL(sys_sigsuspend)
 C_LABEL(sys_sigsuspend):
 	call	C_LABEL(do_sigsuspend)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + AOFF_task_ptrace], %l5
 	andcc	%l5, 0x02, %g0
@@ -1319,7 +1327,7 @@
 C_LABEL(sys_rt_sigsuspend):
 	/* Note: %o0, %o1 already have correct value... */
 	call	C_LABEL(do_rt_sigsuspend)
-	 add	%sp, REGWIN_SZ, %o2
+	 add	%sp, STACKFRAME_SZ, %o2
 
 	ld	[%curptr + AOFF_task_ptrace], %l5
 	andcc	%l5, 0x02, %g0
@@ -1337,7 +1345,7 @@
 	.globl	C_LABEL(sys_sigreturn)
 C_LABEL(sys_sigreturn):
 	call	C_LABEL(do_sigreturn)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + AOFF_task_ptrace], %l5
 	andcc	%l5, 0x02, %g0
@@ -1357,7 +1365,7 @@
 	.globl	C_LABEL(sys_rt_sigreturn)
 C_LABEL(sys_rt_sigreturn):
 	call	C_LABEL(do_rt_sigreturn)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	ld	[%curptr + AOFF_task_ptrace], %l5
 	andcc	%l5, 0x02, %g0
@@ -1391,7 +1399,7 @@
 	WRITE_PAUSE
 	mov	%fp, %o1			! arg1:	usp
 	std	%g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
-	add	%sp, REGWIN_SZ, %o2		! arg2:	pt_regs ptr
+	add	%sp, STACKFRAME_SZ, %o2		! arg2:	pt_regs ptr
 	mov	0, %o3
 	call	C_LABEL(do_fork)
 	 mov	%l5, %o7
@@ -1414,7 +1422,7 @@
 	andn	%o1, 7, %o1			! no, align to 8 bytes
 1:
 	std	%g4, [%curptr + AOFF_task_thread + AOFF_thread_fork_kpsr]
-	add	%sp, REGWIN_SZ, %o2		! arg2:	pt_regs ptr
+	add	%sp, STACKFRAME_SZ, %o2		! arg2:	pt_regs ptr
 	mov	0, %o3
 	call	C_LABEL(do_fork)
 	 mov	%l5, %o7
@@ -1435,7 +1443,7 @@
 	sethi	%hi(C_LABEL(do_fork)), %l1
 	mov	0, %o3
 	jmpl	%l1 + %lo(C_LABEL(do_fork)), %g0
-	 add	%sp, REGWIN_SZ, %o2
+	 add	%sp, STACKFRAME_SZ, %o2
 
         .align  4
 linux_sparc_ni_syscall:
@@ -1466,7 +1474,7 @@
 	call	schedule_tail
 	 mov	%g3, %o0
 	b	C_LABEL(ret_sys_call)
-	 ld	[%sp + REGWIN_SZ + PT_I0], %o0
+	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
 
 	/* Linux native and SunOS system calls enter here... */
 	.align	4
@@ -1501,13 +1509,13 @@
 	call	%l7
 	 mov	%i5, %o5
 
-	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	.globl	C_LABEL(ret_sys_call)
 C_LABEL(ret_sys_call):
 	ld	[%curptr + AOFF_task_ptrace], %l6
 	cmp	%o0, -ENOIOCTLCMD
-	ld	[%sp + REGWIN_SZ + PT_PSR], %g3
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
 	set	PSR_C, %g2
 	bgeu	1f
 	 andcc	%l6, 0x02, %l6	
@@ -1515,35 +1523,35 @@
 	/* System call success, clear Carry condition code. */
 	andn	%g3, %g2, %g3
 	clr	%l6
-	st	%g3, [%sp + REGWIN_SZ + PT_PSR]	
+	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]	
 	bne	linux_syscall_trace2
-	 ld	[%sp + REGWIN_SZ + PT_NPC], %l1 /* pc = npc */
+	 ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
 	add	%l1, 0x4, %l2			/* npc = npc+4 */
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
 	b	ret_trap_entry
-	 st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 1:
 	/* System call failure, set Carry condition code.
 	 * Also, get abs(errno) to return to the process.
 	 */
 	sub	%g0, %o0, %o0
 	or	%g3, %g2, %g3
-	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 	mov	1, %l6
-	st	%g3, [%sp + REGWIN_SZ + PT_PSR]
+	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]
 	bne	linux_syscall_trace2
-	 ld	[%sp + REGWIN_SZ + PT_NPC], %l1 /* pc = npc */
+	 ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */
 	add	%l1, 0x4, %l2			/* npc = npc+4 */
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
 	b	ret_trap_entry
-	 st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 linux_syscall_trace2:
 	call	C_LABEL(syscall_trace)
 	 add	%l1, 0x4, %l2			/* npc = npc+4 */
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
 	b	ret_trap_entry
-	 st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 
 	/*
@@ -1581,19 +1589,19 @@
 	mov	%i0, %l5
 
 	call	C_LABEL(do_solaris_syscall)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
-	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 	set	PSR_C, %g2
 	cmp	%o0, -ENOIOCTLCMD
 	bgeu	1f
-	 ld	[%sp + REGWIN_SZ + PT_PSR], %g3
+	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
 
 	/* System call success, clear Carry condition code. */		
 	andn	%g3, %g2, %g3
 	clr	%l6
 	b	2f
-	 st	%g3, [%sp + REGWIN_SZ + PT_PSR]	
+	 st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]	
 
 1:
 	/* System call failure, set Carry condition code.
@@ -1601,9 +1609,9 @@
 	 */
 	sub	%g0, %o0, %o0
 	mov	1, %l6
-	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 	or	%g3, %g2, %g3
-	st	%g3, [%sp + REGWIN_SZ + PT_PSR]
+	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]
 
 	/* Advance the pc and npc over the trap instruction.
 	 * If the npc is unaligned (has a 1 in the lower byte), it means
@@ -1612,19 +1620,19 @@
 	 * nPC (setcontext).
 	 */
 2:
-	ld	[%sp + REGWIN_SZ + PT_NPC], %l1	/* pc  = npc   */
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1	/* pc  = npc   */
 	andcc	%l1, 1, %g0
 	bne	1f
 	 add	%l1, 0x4, %l2			/* npc = npc+4 */
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
 	b	ret_trap_entry
-	 st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 	/* kernel knows what it is doing, fixup npc and continue */
 1:
 	sub	%l1, 1, %l1
  	b	ret_trap_entry	
-	 st	%l1, [%sp + REGWIN_SZ + PT_NPC]
+	 st	%l1, [%sp + STACKFRAME_SZ + PT_NPC]
 
 #ifndef CONFIG_SUNOS_EMUL
 	.align	4
@@ -1637,7 +1645,7 @@
 	nop
 	mov	%i0, %l5
 	call	C_LABEL(do_sunos_syscall)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 #endif
 
 	/* {net, open}bsd system calls enter here... */
@@ -1674,17 +1682,17 @@
 	call	%l7
 	 mov	%i5, %o5
 
-	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 	set	PSR_C, %g2
 	cmp	%o0, -ENOIOCTLCMD
 	bgeu	1f
-	 ld	[%sp + REGWIN_SZ + PT_PSR], %g3
+	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %g3
 
 	/* System call success, clear Carry condition code. */		
 	andn	%g3, %g2, %g3
 	clr	%l6
 	b	2f
-	 st	%g3, [%sp + REGWIN_SZ + PT_PSR]	
+	 st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]	
 
 1:
 	/* System call failure, set Carry condition code.
@@ -1698,17 +1706,17 @@
 	ld	[%o3 + %o0], %o0
 #endif
 	mov	1, %l6
-	st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 	or	%g3, %g2, %g3
-	st	%g3, [%sp + REGWIN_SZ + PT_PSR]
+	st	%g3, [%sp + STACKFRAME_SZ + PT_PSR]
 
 	/* Advance the pc and npc over the trap instruction. */
 2:
-	ld	[%sp + REGWIN_SZ + PT_NPC], %l1	/* pc  = npc   */
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %l1	/* pc  = npc   */
 	add	%l1, 0x4, %l2			/* npc = npc+4 */
-	st	%l1, [%sp + REGWIN_SZ + PT_PC]
+	st	%l1, [%sp + STACKFRAME_SZ + PT_PC]
 	b	ret_trap_entry
-	 st	%l2, [%sp + REGWIN_SZ + PT_NPC]
+	 st	%l2, [%sp + STACKFRAME_SZ + PT_NPC]
 
 /* Saving and restoring the FPU state is best done from lowlevel code.
  *
@@ -1796,7 +1804,7 @@
 
 	.globl	C_LABEL(ndelay)
 C_LABEL(ndelay):
-	save	%sp, -REGWIN_SZ, %sp
+	save	%sp, -STACKFRAME_SZ, %sp
 	mov	%i0, %o0
 	call	.umul
 	 mov	5, %o1
@@ -1805,7 +1813,7 @@
 
 	.globl	C_LABEL(udelay)
 C_LABEL(udelay):
-	save	%sp, -REGWIN_SZ, %sp
+	save	%sp, -STACKFRAME_SZ, %sp
 	mov	%i0, %o0
 	sethi	%hi(0x10c6), %o1
 	call	.umul
@@ -1842,9 +1850,9 @@
 	wr 	%l0, PSR_ET, %psr
 	WRITE_PAUSE
 
-	st	%i0, [%sp + REGWIN_SZ + PT_G0] ! for restarting syscalls
+	st	%i0, [%sp + STACKFRAME_SZ + PT_G0] ! for restarting syscalls
 	call	C_LABEL(sparc_breakpoint)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	RESTORE_ALL
 
@@ -1938,7 +1946,7 @@
 	WRITE_PAUSE
 
 	call	C_LABEL(pcic_nmi)
-	 add	%sp, REGWIN_SZ, %o1	! struct pt_regs *regs
+	 add	%sp, STACKFRAME_SZ, %o1	! struct pt_regs *regs
 	RESTORE_ALL
 
 	.globl	C_LABEL(pcic_nmi_trap_patch)
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/etrap.S linux-2.4.21-rc7/arch/sparc/kernel/etrap.S
--- linux-2.4.21-rc6/arch/sparc/kernel/etrap.S	2000-01-08 21:36:20.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/etrap.S	2003-06-03 10:04:17.000000000 -0700
@@ -86,7 +86,7 @@
 	/* From kernel, allocate more kernel stack and
 	 * build a pt_regs trap frame.
 	 */
-	sub	%fp, (REGWIN_SZ + TRACEREG_SZ), %t_kstack
+	sub	%fp, (STACKFRAME_SZ + TRACEREG_SZ), %t_kstack
 	STORE_PT_ALL(t_kstack, t_psr, t_pc, t_npc, g2)
 
 	/* See if we are in the trap window. */
@@ -127,7 +127,7 @@
 	jmpl	%t_retpc + 0x8, %g0	! return to caller
 	 mov	%t_kstack, %sp		! and onto new kernel stack
 
-#define STACK_OFFSET (TASK_UNION_SIZE - (TRACEREG_SZ + REGWIN_SZ))
+#define STACK_OFFSET (TASK_UNION_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
 trap_setup_from_user:
 	/* We can't use %curptr yet. */
 	LOAD_CURRENT(t_kstack, t_twinmask)
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/head.S linux-2.4.21-rc7/arch/sparc/kernel/head.S
--- linux-2.4.21-rc6/arch/sparc/kernel/head.S	2001-08-14 19:57:28.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/head.S	2003-06-03 10:04:17.000000000 -0700
@@ -1011,7 +1011,7 @@
 
 		/* I want a kernel stack NOW! */
 		set	C_LABEL(init_task_union), %g1
-		set	(TASK_UNION_SIZE - REGWIN_SZ), %g2
+		set	(TASK_UNION_SIZE - STACKFRAME_SZ), %g2
 		add	%g1, %g2, %sp
 		mov	0, %fp			/* And for good luck */
 
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/process.c linux-2.4.21-rc7/arch/sparc/kernel/process.c
--- linux-2.4.21-rc6/arch/sparc/kernel/process.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/process.c	2003-06-03 10:04:17.000000000 -0700
@@ -384,54 +384,6 @@
 	}
 }
 
-static __inline__ void copy_regs(struct pt_regs *dst, struct pt_regs *src)
-{
-	__asm__ __volatile__("ldd\t[%1 + 0x00], %%g2\n\t"
-			     "ldd\t[%1 + 0x08], %%g4\n\t"
-			     "ldd\t[%1 + 0x10], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x00]\n\t"
-			     "std\t%%g4, [%0 + 0x08]\n\t"
-			     "std\t%%o4, [%0 + 0x10]\n\t"
-			     "ldd\t[%1 + 0x18], %%g2\n\t"
-			     "ldd\t[%1 + 0x20], %%g4\n\t"
-			     "ldd\t[%1 + 0x28], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x18]\n\t"
-			     "std\t%%g4, [%0 + 0x20]\n\t"
-			     "std\t%%o4, [%0 + 0x28]\n\t"
-			     "ldd\t[%1 + 0x30], %%g2\n\t"
-			     "ldd\t[%1 + 0x38], %%g4\n\t"
-			     "ldd\t[%1 + 0x40], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x30]\n\t"
-			     "std\t%%g4, [%0 + 0x38]\n\t"
-			     "ldd\t[%1 + 0x48], %%g2\n\t"
-			     "std\t%%o4, [%0 + 0x40]\n\t"
-			     "std\t%%g2, [%0 + 0x48]\n\t" : :
-			     "r" (dst), "r" (src) :
-			     "g2", "g3", "g4", "g5", "o4", "o5");
-}
-
-static __inline__ void copy_regwin(struct reg_window *dst, struct reg_window *src)
-{
-	__asm__ __volatile__("ldd\t[%1 + 0x00], %%g2\n\t"
-			     "ldd\t[%1 + 0x08], %%g4\n\t"
-			     "ldd\t[%1 + 0x10], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x00]\n\t"
-			     "std\t%%g4, [%0 + 0x08]\n\t"
-			     "std\t%%o4, [%0 + 0x10]\n\t"
-			     "ldd\t[%1 + 0x18], %%g2\n\t"
-			     "ldd\t[%1 + 0x20], %%g4\n\t"
-			     "ldd\t[%1 + 0x28], %%o4\n\t"
-			     "std\t%%g2, [%0 + 0x18]\n\t"
-			     "std\t%%g4, [%0 + 0x20]\n\t"
-			     "std\t%%o4, [%0 + 0x28]\n\t"
-			     "ldd\t[%1 + 0x30], %%g2\n\t"
-			     "ldd\t[%1 + 0x38], %%g4\n\t"
-			     "std\t%%g2, [%0 + 0x30]\n\t"
-			     "std\t%%g4, [%0 + 0x38]\n\t" : :
-			     "r" (dst), "r" (src) :
-			     "g2", "g3", "g4", "g5", "o4", "o5");
-}
-
 static __inline__ struct sparc_stackf *
 clone_stackframe(struct sparc_stackf *dst, struct sparc_stackf *src)
 {
@@ -473,8 +425,7 @@
 		struct task_struct *p, struct pt_regs *regs)
 {
 	struct pt_regs *childregs;
-	struct reg_window *new_stack;
-	unsigned long stack_offset;
+	char *new_stack;
 
 #ifndef CONFIG_SMP
 	if(last_task_used_math == current) {
@@ -489,15 +440,18 @@
 #endif
 	}
 
-	/* Calculate offset to stack_frame & pt_regs */
-	stack_offset = TASK_UNION_SIZE - TRACEREG_SZ;
-
-	if(regs->psr & PSR_PS)
-		stack_offset -= REGWIN_SZ;
-	childregs = ((struct pt_regs *) (((unsigned long)p) + stack_offset));
-	copy_regs(childregs, regs);
-	new_stack = (((struct reg_window *) childregs) - 1);
-	copy_regwin(new_stack, (((struct reg_window *) regs) - 1));
+	/*
+	 *  p                      new_stack   childregs
+	 *  !                      !           !             {if(PSR_PS) }
+	 *  V                      V (stk.fr.) V  (pt_regs)  { (stk.fr.) }
+	 *  +----- - - - - - ------+===========+============={+==========}+
+	 */
+	new_stack = (char*)p + TASK_UNION_SIZE;
+	if (regs->psr & PSR_PS)
+		new_stack -= STACKFRAME_SZ;
+	new_stack -= STACKFRAME_SZ + TRACEREG_SZ;
+	memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
+	childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);
 
 	p->thread.ksp = (unsigned long) new_stack;
 	p->thread.kpc = (((unsigned long) ret_from_fork) - 0x8);
@@ -511,16 +465,11 @@
 		extern struct pt_regs fake_swapper_regs;
 
 		p->thread.kregs = &fake_swapper_regs;
-		new_stack = (struct reg_window *)
-			((((unsigned long)p) +
-			  (TASK_UNION_SIZE)) -
-			 (REGWIN_SZ));
+		new_stack += STACKFRAME_SZ + TRACEREG_SZ;
 		childregs->u_regs[UREG_FP] = (unsigned long) new_stack;
 		p->thread.flags |= SPARC_FLAG_KTHREAD;
 		p->thread.current_ds = KERNEL_DS;
-		memcpy((void *)new_stack,
-		       (void *)regs->u_regs[UREG_FP],
-		       sizeof(struct reg_window));
+		memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ);
 		childregs->u_regs[UREG_G6] = (unsigned long) p;
 	} else {
 		p->thread.kregs = childregs;
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/rtrap.S linux-2.4.21-rc7/arch/sparc/kernel/rtrap.S
--- linux-2.4.21-rc6/arch/sparc/kernel/rtrap.S	2001-07-19 18:11:13.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/rtrap.S	2003-06-03 10:04:17.000000000 -0700
@@ -70,16 +70,16 @@
 signal_p:
 	cmp	%g2, 0
 	bz,a	ret_trap_continue
-	 ld	[%sp + REGWIN_SZ + PT_PSR], %t_psr
+	 ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 
 	clr	%o0
 	mov	%l5, %o2
 	mov	%l6, %o3
 	call	C_LABEL(do_signal)
-	 add	%sp, REGWIN_SZ, %o1	! pt_regs ptr
+	 add	%sp, STACKFRAME_SZ, %o1	! pt_regs ptr
 
 	/* Fall through. */
-	ld	[%sp + REGWIN_SZ + PT_PSR], %t_psr
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 	clr	%l6
 ret_trap_continue:
 	wr	%t_psr, 0x0, %psr
@@ -95,7 +95,7 @@
 
 	mov	1, %o1
 	call	C_LABEL(try_to_clear_window_buffer)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	b	signal_p
 	 ld	[%curptr + AOFF_task_sigpending], %g2
@@ -142,7 +142,7 @@
 	 nop
 
 	b	ret_trap_unaligned_pc
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 1:
 	LOAD_PT_YREG(sp, g1)
@@ -155,9 +155,9 @@
 	rett	%t_npc
 	
 ret_trap_unaligned_pc:
-	ld	[%sp + REGWIN_SZ + PT_PC], %o1
-	ld	[%sp + REGWIN_SZ + PT_NPC], %o2
-	ld	[%sp + REGWIN_SZ + PT_PSR], %o3
+	ld	[%sp + STACKFRAME_SZ + PT_PC], %o1
+	ld	[%sp + STACKFRAME_SZ + PT_NPC], %o2
+	ld	[%sp + STACKFRAME_SZ + PT_PSR], %o3
 
 	wr	%t_wim, 0x0, %wim		! or else...
 
@@ -215,7 +215,7 @@
 	WRITE_PAUSE
 
 	call	C_LABEL(window_ret_fault)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	b	signal_p
 	 ld	[%curptr + AOFF_task_sigpending], %g2
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/signal.c linux-2.4.21-rc7/arch/sparc/kernel/signal.c
--- linux-2.4.21-rc6/arch/sparc/kernel/signal.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/signal.c	2003-06-03 10:04:17.000000000 -0700
@@ -792,7 +792,7 @@
 	int window = 0, err;
 
 	synchronize_user_stack();
-	sfp = (svr4_signal_frame_t *) get_sigframe(sa, regs, SVR4_SF_ALIGNED + REGWIN_SZ);
+	sfp = (svr4_signal_frame_t *) get_sigframe(sa, regs, SVR4_SF_ALIGNED + sizeof(struct reg_window));
 
 	if (invalid_frame_pointer (sfp, sizeof (*sfp))){
 #ifdef DEBUG_SIGNALS
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/smp.c linux-2.4.21-rc7/arch/sparc/kernel/smp.c
--- linux-2.4.21-rc6/arch/sparc/kernel/smp.c	2001-12-21 09:41:53.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/smp.c	2003-06-03 10:04:17.000000000 -0700
@@ -104,13 +104,6 @@
 	local_flush_tlb_all();
 }
 
-/* Only broken Intel needs this, thus it should not even be referenced
- * globally...
- */
-void __init initialize_secondary(void)
-{
-}
-
 extern int cpu_idle(void);
 
 /* Activate a secondary processor. */
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/sparc_ksyms.c linux-2.4.21-rc7/arch/sparc/kernel/sparc_ksyms.c
--- linux-2.4.21-rc6/arch/sparc/kernel/sparc_ksyms.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/sparc_ksyms.c	2003-06-03 10:04:17.000000000 -0700
@@ -122,6 +122,7 @@
 EXPORT_SYMBOL(__down_interruptible);
 
 EXPORT_SYMBOL(sparc_valid_addr_bitmap);
+EXPORT_SYMBOL(phys_base);
 
 /* Atomic operations. */
 EXPORT_SYMBOL_PRIVATE(_atomic_add);
@@ -155,7 +156,8 @@
 EXPORT_SYMBOL(mostek_lock);
 EXPORT_SYMBOL(mstk48t02_regs);
 #if CONFIG_SUN_AUXIO
-EXPORT_SYMBOL(auxio_register);
+EXPORT_SYMBOL(set_auxio);
+EXPORT_SYMBOL(get_auxio);
 #endif
 EXPORT_SYMBOL(request_fast_irq);
 EXPORT_SYMBOL(io_remap_page_range);
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/sunos_asm.S linux-2.4.21-rc7/arch/sparc/kernel/sunos_asm.S
--- linux-2.4.21-rc6/arch/sparc/kernel/sunos_asm.S	2000-01-13 12:03:00.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/sunos_asm.S	2003-06-03 10:04:17.000000000 -0700
@@ -16,7 +16,7 @@
 	.align 4
 
 	/* When calling ret_sys_call, %o0 should contain the same
-	 * value as in [%sp + REGWIN_SZ + PT_I0] */
+	 * value as in [%sp + STACKFRAME_SZ + PT_I0] */
 
 	/* SunOS getpid() returns pid in %o0 and ppid in %o1 */
 	.globl	C_LABEL(sunos_getpid)
@@ -25,10 +25,10 @@
 	 nop
 
 	call	C_LABEL(sys_getpid)
-	 st	%o0, [%sp + REGWIN_SZ + PT_I1]
+	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
 
 	b	C_LABEL(ret_sys_call)
-	 st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	/* SunOS getuid() returns uid in %o0 and euid in %o1 */
 	.globl	C_LABEL(sunos_getuid)
@@ -37,10 +37,10 @@
 	 nop
 
 	call	C_LABEL(sys_getuid16)
-	 st	%o0, [%sp + REGWIN_SZ + PT_I1]
+	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
 
 	b	C_LABEL(ret_sys_call)
-	 st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	/* SunOS getgid() returns gid in %o0 and egid in %o1 */
 	.globl	C_LABEL(sunos_getgid)
@@ -49,20 +49,20 @@
 	 nop
 
 	call	C_LABEL(sys_getgid16)
-	 st	%o0, [%sp + REGWIN_SZ + PT_I1]
+	 st	%o0, [%sp + STACKFRAME_SZ + PT_I1]
 
 	b	C_LABEL(ret_sys_call)
-	 st	%o0, [%sp + REGWIN_SZ + PT_I0]
+	 st	%o0, [%sp + STACKFRAME_SZ + PT_I0]
 
 	/* SunOS's execv() call only specifies the argv argument, the
 	 * environment settings are the same as the calling processes.
 	 */
 	.globl	C_LABEL(sunos_execv)
 C_LABEL(sunos_execv):
-	st	%g0, [%sp + REGWIN_SZ + PT_I2]
+	st	%g0, [%sp + STACKFRAME_SZ + PT_I2]
 
 	call	C_LABEL(sparc_execve)
-	 add	%sp, REGWIN_SZ, %o0
+	 add	%sp, STACKFRAME_SZ, %o0
 
 	b	C_LABEL(ret_sys_call)
-	 ld	[%sp + REGWIN_SZ + PT_I0], %o0
+	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/sys_sparc.c linux-2.4.21-rc7/arch/sparc/kernel/sys_sparc.c
--- linux-2.4.21-rc6/arch/sparc/kernel/sys_sparc.c	2001-04-13 20:15:55.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/sys_sparc.c	2003-06-03 10:04:17.000000000 -0700
@@ -140,7 +140,7 @@
 			goto out;
 			}
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	if (call <= MSGCTL) 
@@ -173,7 +173,7 @@
 			err = sys_msgctl (first, second, (struct msqid_ds *) ptr);
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	if (call <= SHMCTL) 
@@ -205,11 +205,11 @@
 			err = sys_shmctl (first, second, (struct shmid_ds *) ptr);
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	else
-		err = -EINVAL;
+		err = -ENOSYS;
 out:
 	return err;
 }
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/trampoline.S linux-2.4.21-rc7/arch/sparc/kernel/trampoline.S
--- linux-2.4.21-rc6/arch/sparc/kernel/trampoline.S	1999-08-04 16:36:41.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/trampoline.S	2003-06-03 10:04:17.000000000 -0700
@@ -63,8 +63,8 @@
 	and	%g4, 0xc, %g4
 	ld	[%g5 + %g4], %g6
 
-	sethi	%hi(TASK_UNION_SIZE - REGWIN_SZ), %sp
-	or	%sp, %lo(TASK_UNION_SIZE - REGWIN_SZ), %sp
+	sethi	%hi(TASK_UNION_SIZE - STACKFRAME_SZ), %sp
+	or	%sp, %lo(TASK_UNION_SIZE - STACKFRAME_SZ), %sp
 	add	%g6, %sp, %sp
 
 	/* Turn on traps (PSR_ET). */
@@ -140,8 +140,8 @@
 	srl	%g3, 1, %g4
 	ld	[%g5 + %g4], %g6
 
-	sethi	%hi(TASK_UNION_SIZE - REGWIN_SZ), %sp
-	or	%sp, %lo(TASK_UNION_SIZE - REGWIN_SZ), %sp
+	sethi	%hi(TASK_UNION_SIZE - STACKFRAME_SZ), %sp
+	or	%sp, %lo(TASK_UNION_SIZE - STACKFRAME_SZ), %sp
 	add	%g6, %sp, %sp
 
 	/* Turn on traps (PSR_ET). */
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/traps.c linux-2.4.21-rc7/arch/sparc/kernel/traps.c
--- linux-2.4.21-rc6/arch/sparc/kernel/traps.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/kernel/traps.c	2003-06-03 10:04:17.000000000 -0700
@@ -152,6 +152,7 @@
 void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
 			    unsigned long psr)
 {
+	extern int do_user_muldiv (struct pt_regs *, unsigned long);
 	siginfo_t info;
 
 	if(psr & PSR_PS)
@@ -160,11 +161,9 @@
 	printk("Ill instr. at pc=%08lx instruction is %08lx\n",
 	       regs->pc, *(unsigned long *)regs->pc);
 #endif
-	if (sparc_cpu_model == sun4c || sparc_cpu_model == sun4) {
-		extern int do_user_muldiv (struct pt_regs *, unsigned long);
-		if (!do_user_muldiv (regs, pc))
-			return;
-	}
+	if (!do_user_muldiv (regs, pc))
+		return;
+
 	info.si_signo = SIGILL;
 	info.si_errno = 0;
 	info.si_code = ILL_ILLOPC;
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/windows.c linux-2.4.21-rc7/arch/sparc/kernel/windows.c
--- linux-2.4.21-rc6/arch/sparc/kernel/windows.c	2001-10-30 15:08:11.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/windows.c	2003-06-03 10:04:17.000000000 -0700
@@ -120,7 +120,7 @@
 		unsigned long sp = tp->rwbuf_stkptrs[window];
 
 		if((sp & 7) ||
-		   copy_to_user((char *) sp, &tp->reg_window[window], REGWIN_SZ))
+		   copy_to_user((char *) sp, &tp->reg_window[window], sizeof(struct reg_window)))
 			do_exit(SIGILL);
 	}
 	tp->w_saved = 0;
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/wof.S linux-2.4.21-rc7/arch/sparc/kernel/wof.S
--- linux-2.4.21-rc6/arch/sparc/kernel/wof.S	2000-01-08 21:36:20.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/wof.S	2003-06-03 10:04:17.000000000 -0700
@@ -234,7 +234,7 @@
 spnwin_patch3:	and	%twin_tmp, 0xff, %twin_tmp	! patched on 7win Sparcs
 		st	%twin_tmp, [%curptr + AOFF_task_thread + AOFF_thread_uwinmask]
 
-#define STACK_OFFSET	(TASK_UNION_SIZE - TRACEREG_SZ - REGWIN_SZ)
+#define STACK_OFFSET (TASK_UNION_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
 
 	sethi	%hi(STACK_OFFSET), %sp
 	or	%sp, %lo(STACK_OFFSET), %sp
diff -urN linux-2.4.21-rc6/arch/sparc/kernel/wuf.S linux-2.4.21-rc7/arch/sparc/kernel/wuf.S
--- linux-2.4.21-rc6/arch/sparc/kernel/wuf.S	2000-01-08 21:36:20.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/kernel/wuf.S	2003-06-03 10:04:17.000000000 -0700
@@ -138,7 +138,7 @@
 C_LABEL(fwin_mmu_patchme):	b	C_LABEL(sun4c_fwin_stackchk)
 				 andcc	%sp, 0x7, %g0
 
-#define STACK_OFFSET (TASK_UNION_SIZE - TRACEREG_SZ - REGWIN_SZ)
+#define STACK_OFFSET (TASK_UNION_SIZE - TRACEREG_SZ - STACKFRAME_SZ)
 
 fwin_user_stack_is_bolixed:
 	/* LOCATION: Window 'W' */
diff -urN linux-2.4.21-rc6/arch/sparc/mm/srmmu.c linux-2.4.21-rc7/arch/sparc/mm/srmmu.c
--- linux-2.4.21-rc6/arch/sparc/mm/srmmu.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc/mm/srmmu.c	2003-06-03 10:04:17.000000000 -0700
@@ -86,7 +86,7 @@
 ctxd_t *srmmu_context_table;
 
 int viking_mxcc_present;
-spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED;
+static spinlock_t srmmu_context_spinlock = SPIN_LOCK_UNLOCKED;
 
 int is_hypersparc;
 
@@ -130,7 +130,7 @@
 void *srmmu_nocache_bitmap;
 int srmmu_nocache_low;
 int srmmu_nocache_used;
-spinlock_t srmmu_nocache_spinlock;
+static spinlock_t srmmu_nocache_spinlock = SPIN_LOCK_UNLOCKED;
 
 /* This makes sense. Honest it does - Anton */
 #define __nocache_pa(VADDR) (((unsigned long)VADDR) - SRMMU_NOCACHE_VADDR + __pa((unsigned long)srmmu_nocache_pool))
diff -urN linux-2.4.21-rc6/arch/sparc/mm/sun4c.c linux-2.4.21-rc7/arch/sparc/mm/sun4c.c
--- linux-2.4.21-rc6/arch/sparc/mm/sun4c.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/mm/sun4c.c	2003-06-03 10:04:17.000000000 -0700
@@ -246,7 +246,7 @@
 	_unused = sun4c_get_context();
 	sun4c_set_context(_unused);
 #ifdef CONFIG_SUN_AUXIO
-	_unused = *AUXREG;
+	_unused = get_auxio();
 #endif
 }
 
diff -urN linux-2.4.21-rc6/arch/sparc/prom/misc.c linux-2.4.21-rc7/arch/sparc/prom/misc.c
--- linux-2.4.21-rc6/arch/sparc/prom/misc.c	2000-08-28 21:20:03.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc/prom/misc.c	2003-06-03 10:04:17.000000000 -0700
@@ -74,7 +74,7 @@
 	spin_unlock_irqrestore(&prom_lock, flags);
 	install_linux_ticker();
 #ifdef CONFIG_SUN_AUXIO
-	TURN_ON_LED;
+	set_auxio(AUXIO_LED, 0);
 #endif
 #ifdef CONFIG_SUN_CONSOLE
 	if(!serial_console && prom_palette)
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/auxio.c linux-2.4.21-rc7/arch/sparc64/kernel/auxio.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/auxio.c	2001-04-26 22:17:25.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/auxio.c	2003-06-03 10:04:17.000000000 -0700
@@ -1,28 +1,114 @@
 /* auxio.c: Probing for the Sparc AUXIO register at boot time.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
  */
 
 #include <linux/config.h>
-#include <linux/stddef.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/ioport.h>
 
 #include <asm/oplib.h>
 #include <asm/io.h>
-#include <asm/auxio.h>
 #include <asm/sbus.h>
 #include <asm/ebus.h>
-#include <asm/fhc.h>
-#include <asm/spitfire.h>
-#include <asm/starfire.h>
+#include <asm/auxio.h>
+
+/* This cannot be static, as it is referenced in entry.S */
+unsigned long auxio_register = 0UL;
+
+enum auxio_type {
+	AUXIO_TYPE_NODEV,
+	AUXIO_TYPE_SBUS,
+	AUXIO_TYPE_EBUS
+};
+
+static enum auxio_type auxio_devtype = AUXIO_TYPE_NODEV;
+static spinlock_t auxio_lock = SPIN_LOCK_UNLOCKED;
+
+static void __auxio_sbus_set(u8 bits_on, u8 bits_off)
+{
+	if(auxio_register) {
+		unsigned char regval;
+		unsigned long flags;
+		unsigned char newval;
+
+		spin_lock_irqsave(&auxio_lock, flags);
+
+		regval =  sbus_readb(auxio_register);
+		newval =  regval | bits_on;
+		newval &= ~bits_off;
+		newval &= ~AUXIO_AUX1_MASK;
+		sbus_writeb(newval, auxio_register);
+		
+		spin_unlock_irqrestore(&auxio_lock, flags);
+	}
+}
+
+static void __auxio_ebus_set(u8 bits_on, u8 bits_off)
+{
+	if(auxio_register) {
+		unsigned char regval;
+		unsigned long flags;
+		unsigned char newval;
+
+		spin_lock_irqsave(&auxio_lock, flags);
+
+		regval =  (u8)readl(auxio_register);
+		newval =  regval | bits_on;
+		newval &= ~bits_off;
+		writel((u32)newval, auxio_register);
+
+		spin_unlock_irqrestore(&auxio_lock, flags);
+	}
+}
+
+static inline void __auxio_ebus_set_led(int on)
+{
+	(on) ? __auxio_ebus_set(AUXIO_PCIO_LED, 0) :
+		__auxio_ebus_set(0, AUXIO_PCIO_LED) ;
+}
 
-/* Probe and map in the Auxiliary I/O register */
-unsigned long auxio_register = 0;
+static inline void __auxio_sbus_set_led(int on)
+{
+	(on) ? __auxio_sbus_set(AUXIO_AUX1_LED, 0) :
+		__auxio_sbus_set(0, AUXIO_AUX1_LED) ;
+}
+
+void auxio_set_led(int on)
+{
+	switch(auxio_devtype) {
+	case AUXIO_TYPE_SBUS:
+		__auxio_sbus_set_led(on);
+		break;
+	case AUXIO_TYPE_EBUS:
+		__auxio_ebus_set_led(on);
+		break;
+	default:
+		break;
+	}
+}
+
+static inline void __auxio_sbus_set_lte(int on)
+{
+	(on) ? __auxio_sbus_set(AUXIO_AUX1_LTE, 0) : 
+		__auxio_sbus_set(0, AUXIO_AUX1_LTE) ;
+}
+
+void auxio_set_lte(int on)
+{
+	switch(auxio_devtype) {
+	case AUXIO_TYPE_SBUS:
+		__auxio_sbus_set_lte(on);
+		break;
+	case AUXIO_TYPE_EBUS:
+		/* FALL-THROUGH */
+	default:
+		break;
+	}
+}
 
 void __init auxio_probe(void)
 {
@@ -37,11 +123,15 @@
         }
 
 found_sdev:
-	if (!sdev) {
+	if (sdev) {
+		auxio_devtype  = AUXIO_TYPE_SBUS;
+		auxio_register = sbus_ioremap(&sdev->resource[0], 0,
+		  		sdev->reg_addrs[0].reg_size, "auxiliaryIO");
+	}
 #ifdef CONFIG_PCI
+	else {
 		struct linux_ebus *ebus;
 		struct linux_ebus_device *edev = 0;
-		unsigned long led_auxio;
 
 		for_each_ebus(ebus) {
 			for_each_ebusdev(edev, ebus) {
@@ -50,19 +140,12 @@
 			}
 		}
 	ebus_done:
-
 		if (edev) {
-			led_auxio = edev->resource[0].start;
-			outl(0x01, led_auxio);
-			return;
+			auxio_devtype  = AUXIO_TYPE_EBUS;
+			auxio_register = (unsigned long)
+				ioremap(edev->resource[0].start, sizeof(u32));
 		}
-#endif
-		auxio_register = 0UL;
-		return;
 	}
-
-	/* Map the register both read and write */
-	auxio_register = sbus_ioremap(&sdev->resource[0], 0,
-				      sdev->reg_addrs[0].reg_size, "auxiliaryIO");
-	TURN_ON_LED;
+	auxio_set_led(AUXIO_LED_ON);
+#endif
 }
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/entry.S linux-2.4.21-rc7/arch/sparc64/kernel/entry.S
--- linux-2.4.21-rc6/arch/sparc64/kernel/entry.S	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/entry.S	2003-06-03 10:04:17.000000000 -0700
@@ -20,6 +20,7 @@
 #include <asm/processor.h>
 #include <asm/visasm.h>
 #include <asm/estate.h>
+#include <asm/auxio.h>
 
 /* #define SYSCALL_TRACING	1 */
 
@@ -662,9 +663,11 @@
 	sethi		%hi(auxio_register), %g1
 	ldx		[%g1 + %lo(auxio_register)], %g7
 	lduba		[%g7] ASI_PHYS_BYPASS_EC_E, %g5
-	or		%g5, 0xc2, %g5
+	or		%g5, AUXIO_AUX1_FTCNT, %g5
+/*	andn		%g5, AUXIO_AUX1_MASK, %g5 */
 	stba		%g5, [%g7] ASI_PHYS_BYPASS_EC_E
-	andn		%g5, 0x02, %g5
+	andn		%g5, AUXIO_AUX1_FTCNT, %g5
+/*	andn		%g5, AUXIO_AUX1_MASK, %g5 */
 
 	nop; nop;  nop; nop;  nop; nop;
 	nop; nop;  nop; nop;  nop; nop;
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/ioctl32.c linux-2.4.21-rc7/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/ioctl32.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/ioctl32.c	2003-06-03 10:04:18.000000000 -0700
@@ -555,69 +555,38 @@
 	return err;
 }
 
-static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+static __inline__ void *alloc_user_space(long len)
 {
-	struct ifreq ifr;
-	mm_segment_t old_fs;
-	int err, len;
-	u32 data, ethcmd;
-	
-	if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
-		return -EFAULT;
-	ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
-	if (!ifr.ifr_data)
-		return -EAGAIN;
+	struct pt_regs *regs = current->thread.kregs;
+	unsigned long usp = regs->u_regs[UREG_I6];
 
-	__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+	if (!(current->thread.flags & SPARC_FLAG_32BIT))
+		usp += STACK_BIAS;
 
-	if (get_user(ethcmd, (u32 *)A(data))) {
-		err = -EFAULT;
-		goto out;
-	}
-	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:	len = sizeof(struct ethtool_drvinfo); break;
-	case ETHTOOL_GMSGLVL:
-	case ETHTOOL_SMSGLVL:
-	case ETHTOOL_GLINK:
-	case ETHTOOL_NWAY_RST:	len = sizeof(struct ethtool_value); break;
-	case ETHTOOL_GREGS: {
-		struct ethtool_regs *regaddr = (struct ethtool_regs *)A(data);
-		/* darned variable size arguments */
-		if (get_user(len, (u32 *)&regaddr->len)) {
-			err = -EFAULT;
-			goto out;
-		}
-		len += sizeof(struct ethtool_regs);
-		break;
-	}
-	case ETHTOOL_GSET:
-	case ETHTOOL_SSET:	len = sizeof(struct ethtool_cmd); break;
-	default:
-		err = -EOPNOTSUPP;
-		goto out;
-	}
+	return (void *) (usp - len);
+}
 
-	if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) {
-		err = -EFAULT;
-		goto out;
-	}
+static int ethtool_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq *ifr;
+	struct ifreq32 *ifr32;
+	u32 data;
+	void *datap;
+	
+	ifr = alloc_user_space(sizeof(*ifr));
+	ifr32 = (struct ifreq32 *) arg;
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
-	set_fs (old_fs);
-	if (!err) {
-		u32 data;
+	if (copy_in_user(&ifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
+		return -EFAULT;
 
-		__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
-		len = copy_to_user((char *)A(data), ifr.ifr_data, len);
-		if (len)
-			err = -EFAULT;
-	}
+	if (get_user(data, &ifr32->ifr_ifru.ifru_data))
+		return -EFAULT;
 
-out:
-	free_page((unsigned long)ifr.ifr_data);
-	return err;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &ifr->ifr_ifru.ifru_data))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) ifr);
 }
 
 static int bond_ioctl(unsigned long fd, unsigned int cmd, unsigned long arg)
@@ -672,17 +641,6 @@
 	return err;
 }
 
-static __inline__ void *alloc_user_space(long len)
-{
-	struct pt_regs *regs = current->thread.kregs;
-	unsigned long usp = regs->u_regs[UREG_I6];
-
-	if (!(current->thread.flags & SPARC_FLAG_32BIT))
-		usp += STACK_BIAS;
-
-	return (void *) (usp - len);
-}
-
 static int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	struct ifreq *u_ifreq64;
@@ -1046,61 +1004,113 @@
 	__kernel_caddr_t32	transp;
 };
 
-static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+static int do_cmap_ptr(__u16 **ptr64, __u32 *ptr32)
 {
-	mm_segment_t old_fs = get_fs();
-	u32 red = 0, green = 0, blue = 0, transp = 0;
+	__u32 data;
+	void *datap;
+
+	if (get_user(data, ptr32))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, ptr64))
+		return -EFAULT;
+	return 0;
+}
+
+static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct fb_cmap *cmap;
+	struct fb_cmap32 *cmap32;
+	int err;
+
+	cmap = alloc_user_space(sizeof(*cmap));
+	cmap32 = (struct fb_cmap32 *) arg;
+
+	if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
+		return -EFAULT;
+
+	if (do_cmap_ptr(&cmap->red, &cmap32->red) ||
+	    do_cmap_ptr(&cmap->green, &cmap32->green) ||
+	    do_cmap_ptr(&cmap->blue, &cmap32->blue) ||
+	    do_cmap_ptr(&cmap->transp, &cmap32->transp))
+		return -EFAULT;
+
+	err = sys_ioctl(fd, cmd, (unsigned long) cmap);
+
+	if (!err) {
+		if (copy_in_user(&cmap32->start,
+				 &cmap->start,
+				 2 * sizeof(__u32)))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
+				  struct fb_fix_screeninfo32 *fix32)
+{
+	__u32 data;
+	int err;
+
+	err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
+
+	data = (__u32) (unsigned long) fix->smem_start;
+	err |= put_user(data, &fix32->smem_start);
+
+	err |= put_user(fix->smem_len, &fix32->smem_len);
+	err |= put_user(fix->type, &fix32->type);
+	err |= put_user(fix->type_aux, &fix32->type_aux);
+	err |= put_user(fix->visual, &fix32->visual);
+	err |= put_user(fix->xpanstep, &fix32->xpanstep);
+	err |= put_user(fix->ypanstep, &fix32->ypanstep);
+	err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
+	err |= put_user(fix->line_length, &fix32->line_length);
+
+	data = (__u32) (unsigned long) fix->mmio_start;
+	err |= put_user(data, &fix32->mmio_start);
+
+	err |= put_user(fix->mmio_len, &fix32->mmio_len);
+	err |= put_user(fix->accel, &fix32->accel);
+	err |= copy_to_user(fix32->reserved, fix->reserved,
+			    sizeof(fix->reserved));
+
+	return err;
+}
+
+static int fb_get_fscreeninfo(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs;
 	struct fb_fix_screeninfo fix;
-	struct fb_cmap cmap;
-	void *karg;
-	int err = 0;
+	struct fb_fix_screeninfo32 *fix32;
+	int err;
+
+	fix32 = (struct fb_fix_screeninfo32 *) arg;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long) &fix);
+	set_fs(old_fs);
+
+	if (!err)
+		err = do_fscreeninfo_to_user(&fix, fix32);
+
+	return err;
+}
+
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	int err;
 
-	memset(&cmap, 0, sizeof(cmap));
 	switch (cmd) {
 	case FBIOGET_FSCREENINFO:
-		karg = &fix;
+		err = fb_get_fscreeninfo(fd,cmd, arg);
 		break;
+
 	case FBIOGETCMAP:
 	case FBIOPUTCMAP:
-		karg = &cmap;
-		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
-		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
-		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
-		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
-		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
-		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-		err = -ENOMEM;
-		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.red)
-			goto out;
-		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.green)
-			goto out;
-		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-		if (!cmap.blue)
-			goto out;
-		if (transp) {
-			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
-			if (!cmap.transp)
-				goto out;
-		}
-			
-		if (cmd == FBIOGETCMAP)
-			break;
-
-		err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16));
-		err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16));
-		if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16));
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
+		err = fb_getput_cmap(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -1109,47 +1119,10 @@
 				       "cmd(%08x) arg(%08lx)\n",
 				       __FUNCTION__, fd, cmd, arg);
 		} while(0);
-		return -ENOSYS;
-	}
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)karg);
-	set_fs(old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-	case FBIOGET_FSCREENINFO:
-		err = __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->id, (char *)fix.id, sizeof(fix.id));
-		err |= __put_user((__u32)(unsigned long)fix.smem_start, &((struct fb_fix_screeninfo32 *)arg)->smem_start);
-		err |= __put_user(fix.smem_len, &((struct fb_fix_screeninfo32 *)arg)->smem_len);
-		err |= __put_user(fix.type, &((struct fb_fix_screeninfo32 *)arg)->type);
-		err |= __put_user(fix.type_aux, &((struct fb_fix_screeninfo32 *)arg)->type_aux);
-		err |= __put_user(fix.visual, &((struct fb_fix_screeninfo32 *)arg)->visual);
-		err |= __put_user(fix.xpanstep, &((struct fb_fix_screeninfo32 *)arg)->xpanstep);
-		err |= __put_user(fix.ypanstep, &((struct fb_fix_screeninfo32 *)arg)->ypanstep);
-		err |= __put_user(fix.ywrapstep, &((struct fb_fix_screeninfo32 *)arg)->ywrapstep);
-		err |= __put_user(fix.line_length, &((struct fb_fix_screeninfo32 *)arg)->line_length);
-		err |= __put_user((__u32)(unsigned long)fix.mmio_start, &((struct fb_fix_screeninfo32 *)arg)->mmio_start);
-		err |= __put_user(fix.mmio_len, &((struct fb_fix_screeninfo32 *)arg)->mmio_len);
-		err |= __put_user(fix.accel, &((struct fb_fix_screeninfo32 *)arg)->accel);
-		err |= __copy_to_user((char *)((struct fb_fix_screeninfo32 *)arg)->reserved, (char *)fix.reserved, sizeof(fix.reserved));
+		err = -ENOSYS;
 		break;
-	case FBIOGETCMAP:
-		err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16));
-		err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16));
-		err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16));
-		if (cmap.transp)
-			err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16));
-		break;
-	case FBIOPUTCMAP:
-		break;
-	}
-	if (err)
-		err = -EFAULT;
+	};
 
-out:	if (cmap.red) kfree(cmap.red);
-	if (cmap.green) kfree(cmap.green);
-	if (cmap.blue) kfree(cmap.blue);
-	if (cmap.transp) kfree(cmap.transp);
 	return err;
 }
 
@@ -1513,200 +1486,118 @@
 	u32 iov_len;
 } sg_iovec32_t;
 
-static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+static int sg_build_iovec(sg_io_hdr_t *sgio, void *dxferp, u16 iovec_count)
 {
-	sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
-	sg_iovec_t *kiov;
+	sg_iovec_t *iov = (sg_iovec_t *) (sgio + 1);
+	sg_iovec32_t *iov32 = dxferp;
 	int i;
 
-	sgp->dxferp = kmalloc(sgp->iovec_count *
-			      sizeof(sg_iovec_t), GFP_KERNEL);
-	if (!sgp->dxferp)
-		return -ENOMEM;
-	memset(sgp->dxferp, 0,
-	       sgp->iovec_count * sizeof(sg_iovec_t));
-
-	kiov = (sg_iovec_t *) sgp->dxferp;
-	for (i = 0; i < sgp->iovec_count; i++) {
-		u32 iov_base32;
-		if (__get_user(iov_base32, &uiov->iov_base) ||
-		    __get_user(kiov->iov_len, &uiov->iov_len))
-			return -EFAULT;
+	for (i = 0; i < iovec_count; i++) {
+		u32 base, len;
 
-		kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
-		if (!kiov->iov_base)
-			return -ENOMEM;
-		if (copy_from_user(kiov->iov_base,
-				   (void *) A(iov_base32),
-				   kiov->iov_len))
+		if (get_user(base, &iov32[i].iov_base) ||
+		    get_user(len, &iov32[i].iov_len) ||
+		    put_user((void *)(unsigned long)base, &iov[i].iov_base) ||
+		    put_user(len, &iov[i].iov_len))
 			return -EFAULT;
-
-		uiov++;
-		kiov++;
 	}
 
 	return 0;
 }
 
-static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32)
+static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32);
-	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
-	int i;
+	sg_io_hdr_t *sgio;
+	sg_io_hdr32_t *sgio32;
+	u16 iovec_count;
+	u32 data;
+	void *dxferp;
+	int err;
 
-	for (i = 0; i < sgp->iovec_count; i++) {
-		u32 iov_base32;
+	sgio32 = (sg_io_hdr32_t *) arg;
+	if (get_user(iovec_count, &sgio32->iovec_count))
+		return -EFAULT;
 
-		if (__get_user(iov_base32, &uiov->iov_base))
-			return -EFAULT;
+	{
+		void *new, *top;
 
-		if (copy_to_user((void *) A(iov_base32),
-				 kiov->iov_base,
-				 kiov->iov_len))
-			return -EFAULT;
+		top = alloc_user_space(0);
+		new = alloc_user_space(sizeof(sg_io_hdr_t) +
+				       (iovec_count *
+					sizeof(sg_iovec_t)));
+		if (new > top)
+			return -EINVAL;
 
-		uiov++;
-		kiov++;
+		sgio = new;
 	}
 
-	return 0;
-}
-
-static void free_sg_iovec(sg_io_hdr_t *sgp)
-{
-	sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
-	int i;
+	/* Ok, now construct.  */
+	if (copy_in_user(&sgio->interface_id, &sgio32->interface_id,
+			 (2 * sizeof(int)) +
+			 (2 * sizeof(unsigned char)) +
+			 (1 * sizeof(unsigned short)) +
+			 (1 * sizeof(unsigned int))))
+		return -EFAULT;
 
-	for (i = 0; i < sgp->iovec_count; i++) {
-		if (kiov->iov_base) {
-			kfree(kiov->iov_base);
-			kiov->iov_base = NULL;
-		}
-		kiov++;
+	if (get_user(data, &sgio32->dxferp))
+		return -EFAULT;
+	dxferp = (void *) (unsigned long) data;
+	if (iovec_count) {
+		if (sg_build_iovec(sgio, dxferp, iovec_count))
+			return -EFAULT;
+	} else {
+		if (put_user(dxferp, &sgio->dxferp))
+			return -EFAULT;
 	}
-	kfree(sgp->dxferp);
-	sgp->dxferp = NULL;
-}
 
-static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	sg_io_hdr32_t *sg_io32;
-	sg_io_hdr_t sg_io64;
-	u32 dxferp32, cmdp32, sbp32;
-	mm_segment_t old_fs;
-	int err = 0;
+	{
+		unsigned char *cmdp, *sbp;
 
-	sg_io32 = (sg_io_hdr32_t *)arg;
-	err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
-	err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
-	err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
-	err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
-	err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
-	err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
-	err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
-	err |= __get_user(sg_io64.flags, &sg_io32->flags);
-	err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
-
-	sg_io64.dxferp = NULL;
-	sg_io64.cmdp = NULL;
-	sg_io64.sbp = NULL;
-
-	err |= __get_user(cmdp32, &sg_io32->cmdp);
-	sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
-	if (!sg_io64.cmdp) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(sg_io64.cmdp,
-			   (void *) A(cmdp32),
-			   sg_io64.cmd_len)) {
-		err = -EFAULT;
-		goto out;
-	}
-
-	err |= __get_user(sbp32, &sg_io32->sbp);
-	sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
-	if (!sg_io64.sbp) {
-		err = -ENOMEM;
-		goto out;
-	}
-	if (copy_from_user(sg_io64.sbp,
-			   (void *) A(sbp32),
-			   sg_io64.mx_sb_len)) {
-		err = -EFAULT;
-		goto out;
-	}
+		if (get_user(data, &sgio32->cmdp))
+			return -EFAULT;
+		cmdp = (unsigned char *) (unsigned long) data;
 
-	err |= __get_user(dxferp32, &sg_io32->dxferp);
-	if (sg_io64.iovec_count) {
-		int ret;
+		if (get_user(data, &sgio32->sbp))
+			return -EFAULT;
+		sbp = (unsigned char *) (unsigned long) data;
 
-		if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
-			err = ret;
-			goto out;
-		}
-	} else {
-		sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
-		if (!sg_io64.dxferp) {
-			err = -ENOMEM;
-			goto out;
-		}
-		if (copy_from_user(sg_io64.dxferp,
-				   (void *) A(dxferp32),
-				   sg_io64.dxfer_len)) {
-			err = -EFAULT;
-			goto out;
-		}
+		if (put_user(cmdp, &sgio->cmdp) ||
+		    put_user(sbp, &sgio->sbp))
+			return -EFAULT;
 	}
 
-	/* Unused internally, do not even bother to copy it over. */
-	sg_io64.usr_ptr = NULL;
+	if (copy_in_user(&sgio->timeout, &sgio32->timeout,
+			 3 * sizeof(int)))
+		return -EFAULT;
 
-	if (err)
+	if (get_user(data, &sgio32->usr_ptr))
+		return -EFAULT;
+	if (put_user((void *)(unsigned long)data, &sgio->usr_ptr))
 		return -EFAULT;
 
-	old_fs = get_fs();
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
-	set_fs (old_fs);
+	if (copy_in_user(&sgio->status, &sgio32->status,
+			 (4 * sizeof(unsigned char)) +
+			 (2 * sizeof(unsigned (short))) +
+			 (3 * sizeof(int))))
+		return -EFAULT;
 
-	if (err < 0)
-		goto out;
+	err = sys_ioctl(fd, cmd, (unsigned long) sgio);
 
-	err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
-	err |= __put_user(sg_io64.status, &sg_io32->status);
-	err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
-	err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
-	err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
-	err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
-	err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
-	err |= __put_user(sg_io64.resid, &sg_io32->resid);
-	err |= __put_user(sg_io64.duration, &sg_io32->duration);
-	err |= __put_user(sg_io64.info, &sg_io32->info);
-	err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
-	if (sg_io64.dxferp) {
-		if (sg_io64.iovec_count)
-			err |= copy_back_sg_iovec(&sg_io64, dxferp32);
-		else
-			err |= copy_to_user((void *)A(dxferp32),
-					    sg_io64.dxferp,
-					    sg_io64.dxfer_len);
-	}
-	if (err)
-		err = -EFAULT;
+	if (err >= 0) {
+		void *datap;
 
-out:
-	if (sg_io64.cmdp)
-		kfree(sg_io64.cmdp);
-	if (sg_io64.sbp)
-		kfree(sg_io64.sbp);
-	if (sg_io64.dxferp) {
-		if (sg_io64.iovec_count) {
-			free_sg_iovec(&sg_io64);
-		} else {
-			kfree(sg_io64.dxferp);
-		}
+		if (copy_in_user(&sgio32->pack_id, &sgio->pack_id,
+				 sizeof(int)) ||
+		    get_user(datap, &sgio->usr_ptr) ||
+		    put_user((u32)(unsigned long)datap,
+			     &sgio32->usr_ptr) ||
+		    copy_in_user(&sgio32->status, &sgio->status,
+				 (4 * sizeof(unsigned char)) +
+				 (2 * sizeof(unsigned short)) +
+				 (3 * sizeof(int))))
+			err = -EFAULT;
 	}
+
 	return err;
 }
 
@@ -1757,37 +1648,65 @@
 };
 #define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
 
+static int ppp_gidle(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ppp_idle *idle;
+	struct ppp_idle32 *idle32;
+	__kernel_time_t xmit, recv;
+	int err;
+
+	idle = alloc_user_space(sizeof(*idle));
+	idle32 = (struct ppp_idle32 *) arg;
+
+	err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle);
+
+	if (!err) {
+		if (get_user(xmit, &idle->xmit_idle) ||
+		    get_user(recv, &idle->recv_idle) ||
+		    put_user(xmit, &idle32->xmit_idle) ||
+		    put_user(recv, &idle32->recv_idle))
+			err = -EFAULT;
+	}
+	return err;
+}
+
+static int ppp_scompress(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ppp_option_data *odata;
+	struct ppp_option_data32 *odata32;
+	__u32 data;
+	void *datap;
+
+	odata = alloc_user_space(sizeof(*odata));
+	odata32 = (struct ppp_option_data32 *) arg;
+
+	if (get_user(data, &odata32->ptr))
+		return -EFAULT;
+
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &odata->ptr))
+		return -EFAULT;
+
+	if (copy_in_user(&odata->length, &odata32->length,
+			 sizeof(__u32) + sizeof(int)))
+		return -EFAULT;
+
+	return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata);
+}
+
 static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t old_fs = get_fs();
-	struct ppp_option_data32 data32;
-	struct ppp_option_data data;
-	struct ppp_idle32 idle32;
-	struct ppp_idle idle;
-	unsigned int kcmd;
-	void *karg;
-	int err = 0;
+	int err;
 
 	switch (cmd) {
 	case PPPIOCGIDLE32:
-		kcmd = PPPIOCGIDLE;
-		karg = &idle;
+		err = ppp_gidle(fd, cmd, arg);
 		break;
+
 	case PPPIOCSCOMPRESS32:
-		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
-			return -EFAULT;
-		data.ptr = kmalloc (data32.length, GFP_KERNEL);
-		if (!data.ptr)
-			return -ENOMEM;
-		if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) {
-			kfree(data.ptr);
-			return -EFAULT;
-		}
-		data.length = data32.length;
-		data.transmit = data32.transmit;
-		kcmd = PPPIOCSCOMPRESS;
-		karg = &data;
+		err = ppp_scompress(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -1796,26 +1715,10 @@
 				       "cmd(%08x) arg(%08x)\n",
 				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-	set_fs (old_fs);
-	switch (cmd) {
-	case PPPIOCGIDLE32:
-		if (err)
-			return err;
-		idle32.xmit_idle = idle.xmit_idle;
-		idle32.recv_idle = idle.recv_idle;
-		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
-			return -EFAULT;
-		break;
-	case PPPIOCSCOMPRESS32:
-		kfree(data.ptr);
-		break;
-	default:
+		err = -EINVAL;
 		break;
-	}
+	};
+
 	return err;
 }
 
@@ -1943,12 +1846,6 @@
 	return err ? -EFAULT: 0;
 }
 
-struct cdrom_read32 {
-	int			cdread_lba;
-	__kernel_caddr_t32	cdread_bufaddr;
-	int			cdread_buflen;
-};
-
 struct cdrom_read_audio32 {
 	union cdrom_addr	addr;
 	u_char			addr_format;
@@ -1962,60 +1859,94 @@
 	unsigned int		buflen;
 	int			stat;
 	__kernel_caddr_t32	sense;
-	__kernel_caddr_t32	reserved[3];
+	unsigned char		data_direction;
+	int			quiet;
+	int			timeout;
+	__kernel_caddr_t32	reserved[1];
 };
 
+static int cdrom_do_read_audio(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct cdrom_read_audio *cdread_audio;
+	struct cdrom_read_audio32 *cdread_audio32;
+	__u32 data;
+	void *datap;
+
+	cdread_audio = alloc_user_space(sizeof(*cdread_audio));
+	cdread_audio32 = (struct cdrom_read_audio32 *) arg;
+
+	if (copy_in_user(&cdread_audio->addr,
+			 &cdread_audio32->addr,
+			 (sizeof(*cdread_audio32) -
+			  sizeof(__kernel_caddr_t32))))
+		return -EFAULT;
+
+	if (get_user(data, &cdread_audio32->buf))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &cdread_audio->buf))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) cdread_audio);
+}
+
+static int __cgc_do_ptr(void **ptr64, __u32 *ptr32)
+{
+	u32 data;
+	void *datap;
+
+	if (get_user(data, ptr32))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, ptr64))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int cdrom_do_generic_command(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct cdrom_generic_command *cgc;
+	struct cdrom_generic_command32 *cgc32;
+	unsigned char dir;
+
+	cgc = alloc_user_space(sizeof(*cgc));
+	cgc32 = (struct cdrom_generic_command32 *) arg;
+
+	if (copy_in_user(&cgc->cmd, &cgc32->cmd, sizeof(cgc->cmd)) ||
+	    __cgc_do_ptr((void **) &cgc->buffer, &cgc32->buffer) ||
+	    copy_in_user(&cgc->buflen, &cgc32->buflen,
+			 (sizeof(unsigned int) + sizeof(int))) ||
+	    __cgc_do_ptr((void **) &cgc->sense, &cgc32->sense))
+		return -EFAULT;
+
+	if (get_user(dir, &cgc->data_direction) ||
+	    put_user(dir, &cgc32->data_direction))
+		return -EFAULT;
+
+	if (copy_in_user(&cgc->quiet, &cgc32->quiet,
+			 2 * sizeof(int)))
+		return -EFAULT;
+
+	if (__cgc_do_ptr(&cgc->reserved[0], &cgc32->reserved[0]))
+		return -EFAULT;
+
+	return sys_ioctl(fd, cmd, (unsigned long) cgc);
+}
+
 static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t old_fs = get_fs();
-	struct cdrom_read cdread;
-	struct cdrom_read_audio cdreadaudio;
-	struct cdrom_generic_command cgc;
-	__kernel_caddr_t32 addr;
-	char *data = 0;
-	void *karg;
-	int err = 0;
+	int err;
 
 	switch(cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		karg = &cdread;
-		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
-		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
-		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
-		if (err)
-			return -EFAULT;
-		data = kmalloc(cdread.cdread_buflen, GFP_KERNEL);
-		if (!data)
-			return -ENOMEM;
-		cdread.cdread_bufaddr = data;
-		break;
 	case CDROMREADAUDIO:
-		karg = &cdreadaudio;
-		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
-		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
-		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
-		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
-		if (err)
-			return -EFAULT;
-		data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL);
-		if (!data)
-			return -ENOMEM;
-		cdreadaudio.buf = data;
+		err = cdrom_do_read_audio(fd, cmd, arg);
 		break;
+
 	case CDROM_SEND_PACKET:
-		karg = &cgc;
-		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
-		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
-		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
-		if (err)
-			return -EFAULT;
-		if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL)
-			return -ENOMEM;
-		cgc.buffer = data;
+		err = cdrom_do_generic_command(fd, cmd, arg);
 		break;
+
 	default:
 		do {
 			static int count;
@@ -2024,32 +1955,11 @@
 				       "cmd(%08x) arg(%08x)\n",
 				       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		} while(0);
-		return -EINVAL;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)karg);
-	set_fs (old_fs);
-	if (err)
-		goto out;
-	switch (cmd) {
-	case CDROMREADMODE2:
-	case CDROMREADMODE1:
-	case CDROMREADRAW:
-	case CDROMREADCOOKED:
-		err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen);
-		break;
-	case CDROMREADAUDIO:
-		err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
-		break;
-	case CDROM_SEND_PACKET:
-		err = copy_to_user((char *)A(addr), data, cgc.buflen);
-		break;
-	default:
+		err = -EINVAL;
 		break;
-	}
-out:	if (data)
-		kfree(data);
-	return err ? -EFAULT : 0;
+	};
+
+	return err;
 }
 
 struct loop_info32 {
@@ -2624,52 +2534,30 @@
 
 static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	struct atm_iobuf32 iobuf32;
-	struct atm_iobuf   iobuf = { 0, NULL };
-	mm_segment_t old_fs;
-	int err;
-
-	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
-	    sizeof(struct atm_iobuf32));
-	if (err)
-		return -EFAULT;
+	struct atm_iobuf   *iobuf;
+	struct atm_iobuf32 *iobuf32;
+	u32 data;
+	void *datap;
+	int len, err;
 
-	iobuf.length = iobuf32.length;
+	iobuf = alloc_user_space(sizeof(*iobuf));
+	iobuf32 = (struct atm_iobuf32 *) arg;
 
-	if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
-		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
-	} else {
-		iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
-		if (iobuf.buffer == NULL) {
-			err = -ENOMEM;
-			goto out;
-		}
-
-		err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length);
-		if (err) {
-			err = -EFAULT;
-			goto out;
-		}
-	}
+	if (get_user(len, &iobuf32->length) ||
+	    get_user(data, &iobuf32->buffer))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(len, &iobuf->length) ||
+	    put_user(datap, &iobuf->buffer))
+		return -EFAULT;
 
-	old_fs = get_fs(); set_fs (KERNEL_DS);
-	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
-	set_fs (old_fs);
-        if(err)
-		goto out;
+	err = sys_ioctl(fd, cmd, (unsigned long)iobuf);
 
-        if(iobuf.buffer && iobuf.length > 0) {
-		err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length);
-		if (err) {
+	if (!err) {
+		if (copy_in_user(&iobuf32->length, &iobuf->length,
+				 sizeof(int)))
 			err = -EFAULT;
-			goto out;
-		}
 	}
-	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
-
- out:
-        if(iobuf32.buffer && iobuf32.length > 0)
-		kfree(iobuf.buffer);
 
 	return err;
 }
@@ -2677,55 +2565,29 @@
 
 static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-        struct atmif_sioc32 sioc32;
-        struct atmif_sioc   sioc = { 0, 0, NULL };
-        mm_segment_t old_fs;
-        int err;
+        struct atmif_sioc   *sioc;
+        struct atmif_sioc32 *sioc32;
+	u32 data;
+	void *datap;
+	int err;
         
-        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
-			     sizeof(struct atmif_sioc32));
-        if (err)
-                return -EFAULT;
+	sioc = alloc_user_space(sizeof(*sioc));
+	sioc32 = (struct atmif_sioc32 *) arg;
 
-        sioc.number = sioc32.number;
-        sioc.length = sioc32.length;
-        
-	if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
-		sioc.arg = (void*)(unsigned long)sioc32.arg;
-        } else {
-                sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
-                if (sioc.arg == NULL) {
-                        err = -ENOMEM;
-			goto out;
-		}
-                
-                err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length);
-                if (err) {
-                        err = -EFAULT;
-                        goto out;
-                }
-        }
-        
-        old_fs = get_fs(); set_fs (KERNEL_DS);
-        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
-        set_fs (old_fs);
-        if(err) {
-                goto out;
+	if (copy_in_user(&sioc->number, &sioc32->number, 2 * sizeof(int)) ||
+	    get_user(data, &sioc32->arg))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &sioc->arg))
+		return -EFAULT;
+
+	err = sys_ioctl(fd, cmd, (unsigned long) sioc);
+
+	if (!err) {
+		if (copy_in_user(&sioc32->length, &sioc->length,
+				 sizeof(int)))
+			err = -EFAULT;
 	}
-        
-        if(sioc.arg && sioc.length > 0) {
-                err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length);
-                if (err) {
-                        err = -EFAULT;
-                        goto out;
-                }
-        }
-        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
-        
- out:
-        if(sioc32.arg && sioc32.length > 0)
-		kfree(sioc.arg);
-        
 	return err;
 }
 
@@ -2747,15 +2609,14 @@
 		return do_atmif_sioc(fd, cmd32, arg);
 	}
 
-		for (i = 0; i < NR_ATM_IOCTL; i++) {
-			if (cmd32 == atm_ioctl_map[i].cmd32) {
-				cmd = atm_ioctl_map[i].cmd;
-				break;
-			}
+	for (i = 0; i < NR_ATM_IOCTL; i++) {
+		if (cmd32 == atm_ioctl_map[i].cmd32) {
+			cmd = atm_ioctl_map[i].cmd;
+			break;
 		}
-	        if (i == NR_ATM_IOCTL) {
+	}
+	if (i == NR_ATM_IOCTL)
 	        return -EINVAL;
-	        }
         
         switch (cmd) {
 	case ATM_GETNAMES:
@@ -4381,48 +4242,33 @@
 
 static int mtd_rw_oob(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
-	mm_segment_t 			old_fs 	= get_fs();
-	struct mtd_oob_buf32	*uarg 	= (struct mtd_oob_buf32 *)arg;
-	struct mtd_oob_buf		karg;
-	u32 tmp;
-	char *ptr;
-	int ret;
-
-	if (get_user(karg.start, &uarg->start) 		||
-	    get_user(karg.length, &uarg->length)	||
-	    get_user(tmp, &uarg->ptr))
-		return -EFAULT;
-
-	ptr = (char *)A(tmp);
-	if (0 >= karg.length) 
-		return -EINVAL;
+	struct mtd_oob_buf	*buf = alloc_user_space(sizeof(*buf));
+	struct mtd_oob_buf32	*buf32 = (struct mtd_oob_buf32 *) arg;
+	u32 data;
+	char *datap;
+	unsigned int real_cmd;
+	int err;
 
-	karg.ptr = kmalloc(karg.length, GFP_KERNEL);
-	if (NULL == karg.ptr)
-		return -ENOMEM;
+	real_cmd = (cmd == MEMREADOOB32) ?
+		MEMREADOOB : MEMWRITEOOB;
 
-	if (copy_from_user(karg.ptr, ptr, karg.length)) {
-		kfree(karg.ptr);
+	if (copy_in_user(&buf->start, &buf32->start,
+			 2 * sizeof(u32)) ||
+	    get_user(data, &buf32->ptr))
+		return -EFAULT;
+	datap = (void *) (unsigned long) data;
+	if (put_user(datap, &buf->ptr))
 		return -EFAULT;
-	}
 
-	set_fs(KERNEL_DS);
-	if (MEMREADOOB32 == cmd) 
-		ret = sys_ioctl(fd, MEMREADOOB, (unsigned long)&karg);
-	else if (MEMWRITEOOB32 == cmd)
-		ret = sys_ioctl(fd, MEMWRITEOOB, (unsigned long)&karg);
-	else
-		ret = -EINVAL;
-	set_fs(old_fs);
+	err = sys_ioctl(fd, real_cmd, (unsigned long) buf);
 
-	if (0 == ret && cmd == MEMREADOOB32) {
-		ret = copy_to_user(ptr, karg.ptr, karg.length);
-		ret |= put_user(karg.start, &uarg->start);
-		ret |= put_user(karg.length, &uarg->length);
+	if (!err) {
+		if (copy_in_user(&buf32->start, &buf->start,
+				 2 * sizeof(u32)))
+			err = -EFAULT;
 	}
 
-	kfree(karg.ptr);
-	return ((0 == ret) ? 0 : -EFAULT);
+	return err;
 }	
 
 /* Fix sizeof(sizeof()) breakage */
@@ -4880,6 +4726,15 @@
 COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
 COMPATIBLE_IOCTL(CDROM_DEBUG)
 COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Ignore cdrom.h about these next 5 ioctls, they absolutely do
+ * not take a struct cdrom_read, instead they take a struct cdrom_msf
+ * which is compatible.
+ */
+COMPATIBLE_IOCTL(CDROMREADMODE2)
+COMPATIBLE_IOCTL(CDROMREADMODE1)
+COMPATIBLE_IOCTL(CDROMREADRAW)
+COMPATIBLE_IOCTL(CDROMREADCOOKED)
+COMPATIBLE_IOCTL(CDROMREADALL)
 /* DVD ioctls */
 COMPATIBLE_IOCTL(DVD_READ_STRUCT)
 COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
@@ -5333,12 +5188,7 @@
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
-HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
 HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
 HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/power.c linux-2.4.21-rc7/arch/sparc64/kernel/power.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/power.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc64/kernel/power.c	2003-06-03 10:04:18.000000000 -0700
@@ -12,14 +12,13 @@
 #include <linux/delay.h>
 
 #include <asm/ebus.h>
+#include <asm/auxio.h>
 
 #define __KERNEL_SYSCALLS__
 #include <linux/unistd.h>
 
 #ifdef CONFIG_PCI
 static unsigned long power_reg = 0UL;
-#define POWER_SYSTEM_OFF (1 << 0)
-#define POWER_COURTESY_OFF (1 << 1)
 
 static DECLARE_WAIT_QUEUE_HEAD(powerd_wait);
 static int button_pressed;
@@ -48,7 +47,7 @@
 			 * same effect, so until I figure out
 			 * what the difference is...
 			 */
-			writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
+			writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg);
 		} else
 #endif /* CONFIG_PCI */
 			if (poweroff_method != NULL) {
@@ -85,6 +84,16 @@
 	return 0;
 }
 
+static int __init has_button_interrupt(struct linux_ebus_device *edev)
+{
+	if (edev->irqs[0] == PCI_IRQ_NONE)
+		return 0;
+	if (!prom_node_has_property(edev->prom_node, "button"))
+		return 0;
+
+	return 1;
+}
+
 void __init power_init(void)
 {
 	struct linux_ebus *ebus;
@@ -107,7 +116,7 @@
 	power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
 	printk("power: Control reg at %016lx ... ", power_reg);
 	poweroff_method = machine_halt; /* able to use the standard poweroff */
-	if (edev->irqs[0] != PCI_IRQ_NONE) {
+	if (has_button_interrupt(edev)) {
 		if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
 			printk("Failed to start power daemon.\n");
 			return;
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/smp.c linux-2.4.21-rc7/arch/sparc64/kernel/smp.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/smp.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/smp.c	2003-06-03 10:04:18.000000000 -0700
@@ -181,10 +181,6 @@
 extern int cpu_idle(void);
 extern void init_IRQ(void);
 
-void initialize_secondary(void)
-{
-}
-
 int start_secondary(void *unused)
 {
 	trap_init();
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/sparc64_ksyms.c linux-2.4.21-rc7/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/sparc64_ksyms.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/sparc64_ksyms.c	2003-06-03 10:04:18.000000000 -0700
@@ -201,7 +201,8 @@
 EXPORT_SYMBOL(mstk48t02_regs);
 EXPORT_SYMBOL(request_fast_irq);
 #if CONFIG_SUN_AUXIO
-EXPORT_SYMBOL(auxio_register);
+EXPORT_SYMBOL(auxio_set_led);
+EXPORT_SYMBOL(auxio_set_lte);
 #endif
 #if CONFIG_SBUS
 EXPORT_SYMBOL(sbus_root);
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/sys_sparc.c linux-2.4.21-rc7/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/sys_sparc.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/sys_sparc.c	2003-06-03 10:04:18.000000000 -0700
@@ -199,7 +199,7 @@
 			goto out;
 			}
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	if (call <= MSGCTL) 
@@ -218,7 +218,7 @@
 			err = sys_msgctl (first, second | IPC_64, (struct msqid_ds *) ptr);
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	if (call <= SHMCTL) 
@@ -236,11 +236,11 @@
 			err = sys_shmctl (first, second | IPC_64, (struct shmid_ds *) ptr);
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	else
-		err = -EINVAL;
+		err = -ENOSYS;
 out:
 	return err;
 }
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/sys_sparc32.c linux-2.4.21-rc7/arch/sparc64/kernel/sys_sparc32.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/sys_sparc32.c	2003-06-03 10:03:32.000000000 -0700
+++ linux-2.4.21-rc7/arch/sparc64/kernel/sys_sparc32.c	2003-06-03 10:04:18.000000000 -0700
@@ -782,7 +782,7 @@
 			err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		};
 	if (call <= MSGCTL) 
@@ -801,7 +801,7 @@
 			err = do_sys32_msgctl (first, second, (void *)AA(ptr));
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 	if (call <= SHMCTL) 
@@ -820,11 +820,11 @@
 			err = do_sys32_shmctl (first, second, (void *)AA(ptr));
 			goto out;
 		default:
-			err = -EINVAL;
+			err = -ENOSYS;
 			goto out;
 		}
 
-	err = -EINVAL;
+	err = -ENOSYS;
 
 out:
 	return err;
diff -urN linux-2.4.21-rc6/arch/sparc64/kernel/traps.c linux-2.4.21-rc7/arch/sparc64/kernel/traps.c
--- linux-2.4.21-rc6/arch/sparc64/kernel/traps.c	2002-11-28 15:53:12.000000000 -0800
+++ linux-2.4.21-rc7/arch/sparc64/kernel/traps.c	2003-06-03 10:04:18.000000000 -0700
@@ -1542,6 +1542,9 @@
 	struct reg_window *rw;
 	int count = 0;
 
+	if (tsk == current)
+		flushw_all();
+
 	fp = ksp + STACK_BIAS;
 	do {
 		/* Bogus frame pointer? */
@@ -1562,6 +1565,15 @@
 		show_trace_raw(tsk, tsk->thread.ksp);
 }
 
+void dump_stack(void)
+{
+	unsigned long ksp;
+
+	__asm__ __volatile__("mov	%%fp, %0"
+			     : "=r" (ksp));
+	show_trace_raw(current, ksp);
+}
+
 void die_if_kernel(char *str, struct pt_regs *regs)
 {
 	extern void __show_regs(struct pt_regs * regs);
diff -urN linux-2.4.21-rc6/drivers/fc4/soc.c linux-2.4.21-rc7/drivers/fc4/soc.c
--- linux-2.4.21-rc6/drivers/fc4/soc.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-rc7/drivers/fc4/soc.c	2003-06-03 10:04:26.000000000 -0700
@@ -40,7 +40,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/auxio.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 
diff -urN linux-2.4.21-rc6/drivers/fc4/socal.c linux-2.4.21-rc7/drivers/fc4/socal.c
--- linux-2.4.21-rc6/drivers/fc4/socal.c	2002-08-02 17:39:43.000000000 -0700
+++ linux-2.4.21-rc7/drivers/fc4/socal.c	2003-06-03 10:04:26.000000000 -0700
@@ -36,7 +36,6 @@
 
 #include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/auxio.h>
 #include <asm/pgtable.h>
 #include <asm/irq.h>
 
diff -urN linux-2.4.21-rc6/drivers/net/sunlance.c linux-2.4.21-rc7/drivers/net/sunlance.c
--- linux-2.4.21-rc6/drivers/net/sunlance.c	2003-06-03 10:03:38.000000000 -0700
+++ linux-2.4.21-rc7/drivers/net/sunlance.c	2003-06-03 10:04:47.000000000 -0700
@@ -1421,7 +1421,7 @@
 				       "'tpe-link-test?'\n", dev->name);
 				printk(KERN_NOTICE "%s: warning: mail any problems "
 				       "to ecd@skynet.be\n", dev->name);
-				set_auxio(AUXIO_LINK_TEST, 0);
+				auxio_set_lte(AUXIO_LTE_ON);
 			}
 no_link_test:
 			lp->auto_select = 1;
diff -urN linux-2.4.21-rc6/drivers/net/tokenring/olympic.c linux-2.4.21-rc7/drivers/net/tokenring/olympic.c
--- linux-2.4.21-rc6/drivers/net/tokenring/olympic.c	2002-11-28 15:53:14.000000000 -0800
+++ linux-2.4.21-rc7/drivers/net/tokenring/olympic.c	2003-06-03 10:04:48.000000000 -0700
@@ -655,8 +655,7 @@
 	printk(" stat_ring[7]: %p\n", &(olympic_priv->olympic_rx_status_ring[7])  );
 
 	printk("RXCDA: %x, rx_ring[0]: %p\n",readl(olympic_mmio+RXCDA),&olympic_priv->olympic_rx_ring[0]);
-	printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr =
-%08x\n",olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; 
+	printk("Rx_ring_dma_addr = %08x, rx_status_dma_addr = %08x\n",olympic_priv->rx_ring_dma_addr,olympic_priv->rx_status_ring_dma_addr) ; 
 #endif
 
 	writew((((readw(olympic_mmio+RXENQ)) & 0x8000) ^ 0x8000) | i,olympic_mmio+RXENQ);
diff -urN linux-2.4.21-rc6/drivers/sbus/char/bbc_envctrl.c linux-2.4.21-rc7/drivers/sbus/char/bbc_envctrl.c
--- linux-2.4.21-rc6/drivers/sbus/char/bbc_envctrl.c	2001-04-12 12:10:25.000000000 -0700
+++ linux-2.4.21-rc7/drivers/sbus/char/bbc_envctrl.c	2003-06-03 10:04:53.000000000 -0700
@@ -571,12 +571,13 @@
 	set_fan_speeds(fp);
 }
 
-void bbc_envctrl_init(void)
+int bbc_envctrl_init(void)
 {
 	struct linux_ebus_child *echild;
 	int temp_index = 0;
 	int fan_index = 0;
 	int devidx = 0;
+	int err = 0;
 
 	while ((echild = bbc_i2c_getdev(devidx++)) != NULL) {
 		if (!strcmp(echild->prom_name, "temperature"))
@@ -585,7 +586,8 @@
 			attach_one_fan(echild, fan_index++);
 	}
 	if (temp_index != 0 && fan_index != 0)
-		kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
+		err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
+	return err;
 }
 
 static void destroy_one_temp(struct bbc_cpu_temperature *tp)
diff -urN linux-2.4.21-rc6/drivers/sbus/char/bbc_i2c.c linux-2.4.21-rc7/drivers/sbus/char/bbc_i2c.c
--- linux-2.4.21-rc6/drivers/sbus/char/bbc_i2c.c	2001-04-12 12:10:25.000000000 -0700
+++ linux-2.4.21-rc7/drivers/sbus/char/bbc_i2c.c	2003-06-03 10:04:53.000000000 -0700
@@ -427,14 +427,15 @@
 	return 0;
 }
 
-extern void bbc_envctrl_init(void);
+extern int bbc_envctrl_init(void);
 extern void bbc_envctrl_cleanup(void);
+static void bbc_i2c_cleanup(void);
 
 static int __init bbc_i2c_init(void)
 {
 	struct linux_ebus *ebus = NULL;
 	struct linux_ebus_device *edev = NULL;
-	int index = 0;
+	int err, index = 0;
 
 	if (tlb_type != cheetah || !bbc_present())
 		return -ENODEV;
@@ -451,11 +452,13 @@
 	if (!index)
 		return -ENODEV;
 
-	bbc_envctrl_init();
-	return 0;
+	err = bbc_envctrl_init();
+	if (err)
+		bbc_i2c_cleanup();
+	return err;
 }
 
-static void __exit bbc_i2c_cleanup(void)
+static void bbc_i2c_cleanup(void)
 {
 	struct bbc_i2c_bus *bp = all_bbc_i2c;
 
diff -urN linux-2.4.21-rc6/drivers/sbus/char/envctrl.c linux-2.4.21-rc7/drivers/sbus/char/envctrl.c
--- linux-2.4.21-rc6/drivers/sbus/char/envctrl.c	2002-02-25 11:38:04.000000000 -0800
+++ linux-2.4.21-rc7/drivers/sbus/char/envctrl.c	2003-06-03 10:04:53.000000000 -0700
@@ -1050,7 +1050,7 @@
 	struct linux_ebus *ebus = NULL;
 	struct linux_ebus_device *edev = NULL;
 	struct linux_ebus_child *edev_child = NULL;
-	int i = 0;
+	int err, i = 0;
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
@@ -1105,9 +1105,11 @@
 	udelay(200);
 
 	/* Register the device as a minor miscellaneous device. */
-	if (misc_register(&envctrl_dev)) {
+	err = misc_register(&envctrl_dev);
+	if (err) {
 		printk("envctrl: Unable to get misc minor %d\n",
 		       envctrl_dev.minor);
+		goto out_iounmap;
 	}
 
 	/* Note above traversal routine post-incremented 'i' to accomodate 
@@ -1122,9 +1124,21 @@
 			i2c_childlist[i].addr, (0 == i) ? ("\n") : (" "));
 	}
 
-	kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
+	err = kernel_thread(kenvctrld, NULL, CLONE_FS | CLONE_FILES);
+	if (err)
+		goto out_deregister;
 
 	return 0;
+
+out_deregister:
+	misc_deregister(&envctrl_dev);
+out_iounmap:
+	iounmap(i2c);
+	for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) {
+		if (i2c_childlist[i].tables)
+			kfree(i2c_childlist[i].tables);
+	}
+	return err;
 #else
 	return -ENODEV;
 #endif
diff -urN linux-2.4.21-rc6/drivers/scsi/sg.c linux-2.4.21-rc7/drivers/scsi/sg.c
--- linux-2.4.21-rc6/drivers/scsi/sg.c	2002-08-02 17:39:44.000000000 -0700
+++ linux-2.4.21-rc7/drivers/scsi/sg.c	2003-06-03 10:05:02.000000000 -0700
@@ -7,7 +7,7 @@
  * Original driver (sg.c):
  *        Copyright (C) 1992 Lawrence Foard
  * Version 2 and 3 extensions to driver:
- *        Copyright (C) 1998 - 2002 Douglas Gilbert
+ *        Copyright (C) 1998 - 2003 Douglas Gilbert
  *
  *  Modified  19-JAN-1998  Richard Gooch <rgooch@atnf.csiro.au>  Devfs support
  *
@@ -19,9 +19,9 @@
  */
 #include <linux/config.h>
 #ifdef CONFIG_PROC_FS
- static char * sg_version_str = "Version: 3.1.24 (20020505)";
+ static char * sg_version_str = "Version: 3.1.25 (20030529)";
 #endif
- static int sg_version_num = 30124; /* 2 digits for each component */
+ static int sg_version_num = 30125; /* 2 digits for each component */
 /*
  *  D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes:
  *      - scsi logging is available via SCSI_LOG_TIMEOUT macros. First
@@ -1884,11 +1884,7 @@
 	    res = sg_u_iovec(hp, iovec_count, j, 1, &usglen, &up);
 	    if (res) return res;
 
-	    for (; k < schp->k_use_sg; ++k, ++sclp) {
-		ksglen = (int)sclp->length;
-		p = sclp->address;
-		if (NULL == p)
-		    break;
+	    for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
 		ok = (SG_USER_MEM != mem_src_arr[k]);
 		if (usglen <= 0)
 		    break;
@@ -1911,6 +1907,9 @@
 		    up += ksglen;
 		    usglen -= ksglen;
 		}
+                ++k;
+                if (k >= schp->k_use_sg)
+                    return 0;
             }
         }
     }
@@ -2040,11 +2039,7 @@
 	    res = sg_u_iovec(hp, iovec_count, j, 0, &usglen, &up);
 	    if (res) return res;
 
-	    for (; k < schp->k_use_sg; ++k, ++sclp) {
-		ksglen = (int)sclp->length;
-		p = sclp->address;
-		if (NULL == p)
-		    break;
+	    for ( ; p; ++sclp, ksglen = (int)sclp->length, p = sclp->address) {
 		ok = (SG_USER_MEM != mem_src_arr[k]);
 		if (usglen <= 0)
 		    break;
@@ -2067,6 +2062,9 @@
 		    up += ksglen;
 		    usglen -= ksglen;
 		}
+                ++k;
+                if (k >= schp->k_use_sg)
+                    return 0;
 	    }
 	}
     }
diff -urN linux-2.4.21-rc6/include/asm-sh/page.h linux-2.4.21-rc7/include/asm-sh/page.h
--- linux-2.4.21-rc6/include/asm-sh/page.h	2001-09-08 12:29:09.000000000 -0700
+++ linux-2.4.21-rc7/include/asm-sh/page.h	2003-06-03 10:06:05.000000000 -0700
@@ -88,6 +88,9 @@
 
 #define virt_to_page(kaddr)	phys_to_page(__pa(kaddr))
 
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
 #ifndef __ASSEMBLY__
 
 /*
diff -urN linux-2.4.21-rc6/include/asm-sparc/auxio.h linux-2.4.21-rc7/include/asm-sparc/auxio.h
--- linux-2.4.21-rc6/include/asm-sparc/auxio.h	1998-01-12 15:15:45.000000000 -0800
+++ linux-2.4.21-rc7/include/asm-sparc/auxio.h	2003-06-03 10:06:05.000000000 -0700
@@ -9,8 +9,6 @@
 #include <asm/system.h>
 #include <asm/vaddrs.h>
 
-extern unsigned char *auxio_register;
-
 /* This register is an unsigned char in IO space.  It does two things.
  * First, it is used to control the front panel LED light on machines
  * that have it (good for testing entry points to trap handlers and irq's)
@@ -31,41 +29,52 @@
 #define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk.  Write only. */
 #define AUXIO_LED         0x01    /* On if set, off if unset. Read/Write */
 
-#define AUXREG   ((volatile unsigned char *)(auxio_register))
+#ifndef __ASSEMBLY__
+
+/* 
+ * NOTE: these routines are implementation dependent-- 
+ * understand the hardware you are querying! 
+ */
+extern void set_auxio(unsigned char bits_on, unsigned char bits_off);
+extern unsigned char get_auxio(void); /* .../asm-sparc/floppy.h */
 
-/* These are available on sun4c */
-#define TURN_ON_LED   if (AUXREG) *AUXREG = (*AUXREG | AUXIO_ORMEIN | AUXIO_LED)
-#define TURN_OFF_LED  if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_LED))
-#define FLIP_LED      if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) ^ AUXIO_LED)
-#define FLPY_MOTORON  if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_DSEL)
-#define FLPY_MOTOROFF if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_DSEL))
-#define FLPY_TCNTON   if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) | AUXIO_FLPY_TCNT)
-#define FLPY_TCNTOFF  if (AUXREG) *AUXREG = ((*AUXREG | AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT))
+/*
+ * The following routines are provided for driver-compatibility
+ * with sparc64 (primarily sunlance.c)
+ */
 
-#ifndef __ASSEMBLY__
-#define set_auxio(bits_on, bits_off) \
+#define AUXIO_LTE_ON    1
+#define AUXIO_LTE_OFF   0
+
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+#define auxio_set_lte(on) \
 do { \
-	unsigned char regval; \
-	unsigned long flags; \
-	save_flags(flags); cli(); \
-	switch(sparc_cpu_model) { \
-	case sun4c: \
-		regval = *AUXREG; \
-		*AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN; \
-		break; \
-	case sun4m: \
-		if(!AUXREG) \
-			break;     /* VME chassic sun4m, no auxio. */ \
-		regval = *AUXREG; \
-		*AUXREG = ((regval | bits_on) & ~bits_off) | AUXIO_ORMEIN4M; \
-		break; \
-	case sun4d: \
-		break; \
-	default: \
-		panic("Can't set AUXIO register on this machine."); \
-	}; \
-	restore_flags(flags); \
-} while(0)
+	if(on) { \
+		set_auxio(AUXIO_LINK_TEST, 0); \
+	} else { \
+		set_auxio(0, AUXIO_LINK_TEST); \
+	} \
+} while (0)
+
+#define AUXIO_LED_ON    1
+#define AUXIO_LED_OFF   0
+
+/* auxio_set_led - Set system front panel LED
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+#define auxio_set_led(on) \
+do { \
+	if(on) { \
+		set_auxio(AUXIO_LED, 0); \
+	} else { \
+		set_auxio(0, AUXIO_LED); \
+	} \
+} while (0)
+
 #endif /* !(__ASSEMBLY__) */
 
 
diff -urN linux-2.4.21-rc6/include/asm-sparc/floppy.h linux-2.4.21-rc7/include/asm-sparc/floppy.h
--- linux-2.4.21-rc6/include/asm-sparc/floppy.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.21-rc7/include/asm-sparc/floppy.h	2003-06-03 10:06:05.000000000 -0700
@@ -115,7 +115,7 @@
 	case 5: /* FD_DATA */
 		return sun_fdc->data_82072;
 	case 7: /* FD_DIR */
-		return (*AUXREG & AUXIO_FLPY_DCHG)? 0x80: 0;
+		return (get_auxio() & AUXIO_FLPY_DCHG)? 0x80: 0;
 	};
 	panic("sun_82072_fd_inb: How did I get here?");
 }
@@ -332,7 +332,7 @@
                 sun_fdops.fd_inb = sun_82072_fd_inb;
                 sun_fdops.fd_outb = sun_82072_fd_outb;
                 fdc_status = &sun_fdc->status_82072;
-                /* printk("AUXIO @0x%p\n", auxio_register); */ /* P3 */
+                /* printk("AUXIO @0x%lx\n", auxio_register); */ /* P3 */
         } else {
                 sun_fdops.fd_inb = sun_82077_fd_inb;
                 sun_fdops.fd_outb = sun_82077_fd_outb;
diff -urN linux-2.4.21-rc6/include/asm-sparc/kgdb.h linux-2.4.21-rc7/include/asm-sparc/kgdb.h
--- linux-2.4.21-rc6/include/asm-sparc/kgdb.h	1998-01-12 15:15:54.000000000 -0800
+++ linux-2.4.21-rc7/include/asm-sparc/kgdb.h	2003-06-03 10:06:05.000000000 -0700
@@ -52,43 +52,43 @@
 #define KGDB_NPC    0x114
 
 #define SAVE_KGDB_GLOBALS(reg) \
-        std     %g0, [%reg + REGWIN_SZ + KGDB_G0]; \
-        std     %g2, [%reg + REGWIN_SZ + KGDB_G2]; \
-        std     %g4, [%reg + REGWIN_SZ + KGDB_G4]; \
-        std     %g6, [%reg + REGWIN_SZ + KGDB_G6];
+        std     %g0, [%reg + STACKFRAME_SZ + KGDB_G0]; \
+        std     %g2, [%reg + STACKFRAME_SZ + KGDB_G2]; \
+        std     %g4, [%reg + STACKFRAME_SZ + KGDB_G4]; \
+        std     %g6, [%reg + STACKFRAME_SZ + KGDB_G6];
 
 #define SAVE_KGDB_INS(reg) \
-        std     %i0, [%reg + REGWIN_SZ + KGDB_I0]; \
-        std     %i2, [%reg + REGWIN_SZ + KGDB_I2]; \
-        std     %i4, [%reg + REGWIN_SZ + KGDB_I4]; \
-        std     %i6, [%reg + REGWIN_SZ + KGDB_I6];
+        std     %i0, [%reg + STACKFRAME_SZ + KGDB_I0]; \
+        std     %i2, [%reg + STACKFRAME_SZ + KGDB_I2]; \
+        std     %i4, [%reg + STACKFRAME_SZ + KGDB_I4]; \
+        std     %i6, [%reg + STACKFRAME_SZ + KGDB_I6];
 
 #define SAVE_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
-        st      %reg_y, [%reg + REGWIN_SZ + KGDB_Y]; \
-        st      %reg_psr, [%reg + REGWIN_SZ + KGDB_PSR]; \
-        st      %reg_wim, [%reg + REGWIN_SZ + KGDB_WIM]; \
-        st      %reg_tbr, [%reg + REGWIN_SZ + KGDB_TBR]; \
-        st      %reg_pc, [%reg + REGWIN_SZ + KGDB_PC]; \
-        st      %reg_npc, [%reg + REGWIN_SZ + KGDB_NPC];
+        st      %reg_y, [%reg + STACKFRAME_SZ + KGDB_Y]; \
+        st      %reg_psr, [%reg + STACKFRAME_SZ + KGDB_PSR]; \
+        st      %reg_wim, [%reg + STACKFRAME_SZ + KGDB_WIM]; \
+        st      %reg_tbr, [%reg + STACKFRAME_SZ + KGDB_TBR]; \
+        st      %reg_pc, [%reg + STACKFRAME_SZ + KGDB_PC]; \
+        st      %reg_npc, [%reg + STACKFRAME_SZ + KGDB_NPC];
 
 #define LOAD_KGDB_GLOBALS(reg) \
-        ld      [%reg + REGWIN_SZ + KGDB_G1], %g1; \
-        ldd     [%reg + REGWIN_SZ + KGDB_G2], %g2; \
-        ldd     [%reg + REGWIN_SZ + KGDB_G4], %g4; \
-        ldd     [%reg + REGWIN_SZ + KGDB_G6], %g6;
+        ld      [%reg + STACKFRAME_SZ + KGDB_G1], %g1; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_G2], %g2; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_G4], %g4; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_G6], %g6;
 
 #define LOAD_KGDB_INS(reg) \
-        ldd     [%reg + REGWIN_SZ + KGDB_I0], %i0; \
-        ldd     [%reg + REGWIN_SZ + KGDB_I2], %i2; \
-        ldd     [%reg + REGWIN_SZ + KGDB_I4], %i4; \
-        ldd     [%reg + REGWIN_SZ + KGDB_I6], %i6;
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I0], %i0; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I2], %i2; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I4], %i4; \
+        ldd     [%reg + STACKFRAME_SZ + KGDB_I6], %i6;
 
 #define LOAD_KGDB_SREGS(reg, reg_y, reg_psr, reg_wim, reg_tbr, reg_pc, reg_npc) \
-	ld	[%reg + REGWIN_SZ + KGDB_Y], %reg_y; \
-	ld	[%reg + REGWIN_SZ + KGDB_PSR], %reg_psr; \
-	ld	[%reg + REGWIN_SZ + KGDB_WIM], %reg_wim; \
-	ld	[%reg + REGWIN_SZ + KGDB_TBR], %reg_tbr; \
-	ld	[%reg + REGWIN_SZ + KGDB_PC], %reg_pc; \
-	ld	[%reg + REGWIN_SZ + KGDB_NPC], %reg_npc;
+	ld	[%reg + STACKFRAME_SZ + KGDB_Y], %reg_y; \
+	ld	[%reg + STACKFRAME_SZ + KGDB_PSR], %reg_psr; \
+	ld	[%reg + STACKFRAME_SZ + KGDB_WIM], %reg_wim; \
+	ld	[%reg + STACKFRAME_SZ + KGDB_TBR], %reg_tbr; \
+	ld	[%reg + STACKFRAME_SZ + KGDB_PC], %reg_pc; \
+	ld	[%reg + STACKFRAME_SZ + KGDB_NPC], %reg_npc;
 
 #endif /* !(_SPARC_KGDB_H) */
diff -urN linux-2.4.21-rc6/include/asm-sparc/processor.h linux-2.4.21-rc7/include/asm-sparc/processor.h
--- linux-2.4.21-rc6/include/asm-sparc/processor.h	2003-06-03 10:03:47.000000000 -0700
+++ linux-2.4.21-rc7/include/asm-sparc/processor.h	2003-06-03 10:06:05.000000000 -0700
@@ -140,7 +140,7 @@
 			     "std\t%%g0, [%0 + %3 + 0x30]\n\t"
 			     "st\t%1, [%0 + %3 + 0x38]\n\t"
 			     "st\t%%g0, [%0 + %3 + 0x3c]"
-			     : : "r" (regs), "r" (sp - REGWIN_SZ), "r" (zero),
+			     : : "r" (regs), "r" (sp - sizeof(struct reg_window)), "r" (zero),
 			     "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0])));
 }
 
diff -urN linux-2.4.21-rc6/include/asm-sparc/ptrace.h linux-2.4.21-rc7/include/asm-sparc/ptrace.h
--- linux-2.4.21-rc6/include/asm-sparc/ptrace.h	1997-03-17 14:54:31.000000000 -0800
+++ linux-2.4.21-rc7/include/asm-sparc/ptrace.h	2003-06-03 10:06:05.000000000 -0700
@@ -58,7 +58,6 @@
 
 #define TRACEREG_SZ   sizeof(struct pt_regs)
 #define STACKFRAME_SZ sizeof(struct sparc_stackf)
-#define REGWIN_SZ     sizeof(struct reg_window)
 
 #ifdef __KERNEL__
 #define user_mode(regs) (!((regs)->psr & PSR_PS))
@@ -70,7 +69,6 @@
 /* For assembly code. */
 #define TRACEREG_SZ       0x50
 #define STACKFRAME_SZ     0x60
-#define REGWIN_SZ         0x40
 #endif
 
 #include <asm/asm_offsets.h>
diff -urN linux-2.4.21-rc6/include/asm-sparc/system.h linux-2.4.21-rc7/include/asm-sparc/system.h
--- linux-2.4.21-rc6/include/asm-sparc/system.h	2003-06-03 10:03:47.000000000 -0700
+++ linux-2.4.21-rc7/include/asm-sparc/system.h	2003-06-03 10:06:05.000000000 -0700
@@ -109,15 +109,14 @@
 	 * - Anton
 	 */
 #define switch_to(prev, next, last) do {						\
-	__label__ here;									\
-	register unsigned long task_pc asm("o7");					\
 	extern struct task_struct *current_set[NR_CPUS];				\
 	SWITCH_ENTER									\
 	SWITCH_DO_LAZY_FPU								\
 	next->active_mm->cpu_vm_mask |= (1 << smp_processor_id());			\
-	task_pc = ((unsigned long) &&here) - 0x8;					\
 	__asm__ __volatile__(								\
+	"sethi	%%hi(here - 0x8), %%o7\n\t"						\
 	"mov	%%g6, %%g3\n\t"								\
+	"or	%%o7, %%lo(here - 0x8), %%o7\n\t"					\
 	"rd	%%psr, %%g4\n\t"							\
 	"std	%%sp, [%%g6 + %4]\n\t"							\
 	"rd	%%wim, %%g5\n\t"							\
@@ -141,16 +140,16 @@
 	"nop\n\t"									\
 	"nop\n\t"									\
 	"jmpl	%%o7 + 0x8, %%g0\n\t"							\
-	" mov	%%g3, %0\n\t"								\
+	" mov	%%g3, %0\n"								\
+	"here:\n"									\
         : "=&r" (last)									\
         : "r" (&(current_set[hard_smp_processor_id()])), "r" (next),			\
 	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.kpsr)),		\
-	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.ksp)),		\
-	  "r" (task_pc)									\
+	  "i" ((const unsigned long)(&((struct task_struct *)0)->thread.ksp))		\
 	: "g1", "g2", "g3", "g4", "g5", "g7", "l0", "l1", "l3",				\
 	"l4", "l5", "l6", "l7", "i0", "i1", "i2", "i3", "i4", "i5", "o0", "o1", "o2",	\
-	"o3");										\
-here:;  } while(0)
+	"o3", "o7");									\
+	} while(0)
 
 /*
  * Changing the IRQ level on the Sparc.
diff -urN linux-2.4.21-rc6/include/asm-sparc/uaccess.h linux-2.4.21-rc7/include/asm-sparc/uaccess.h
--- linux-2.4.21-rc6/include/asm-sparc/uaccess.h	2001-10-30 15:08:11.000000000 -0800
+++ linux-2.4.21-rc7/include/asm-sparc/uaccess.h	2003-06-03 10:06:05.000000000 -0700
@@ -103,7 +103,7 @@
  * doing multiple accesses to the same area (the user has to do the
  * checks by hand with "access_ok()")
  */
-#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x,ptr) __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 #define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)),__typeof__(*(ptr)))
 
 struct __large_struct { unsigned long buf[100]; };
diff -urN linux-2.4.21-rc6/include/asm-sparc/winmacro.h linux-2.4.21-rc7/include/asm-sparc/winmacro.h
--- linux-2.4.21-rc6/include/asm-sparc/winmacro.h	2000-05-22 09:50:54.000000000 -0700
+++ linux-2.4.21-rc7/include/asm-sparc/winmacro.h	2003-06-03 10:06:05.000000000 -0700
@@ -11,14 +11,6 @@
 #include <asm/ptrace.h>
 #include <asm/psr.h>
 
-/* These are just handy. */
-#define _SV	save	%sp, -REGWIN_SZ, %sp
-#define _RS     restore 
-
-#define FLUSH_ALL_KERNEL_WINDOWS \
-	_SV; _SV; _SV; _SV; _SV; _SV; _SV; \
-	_RS; _RS; _RS; _RS; _RS; _RS; _RS;
-
 /* Store the register window onto the 8-byte aligned area starting
  * at %reg.  It might be %sp, it might not, we don't care.
  */
@@ -45,25 +37,25 @@
 
 /* Loading and storing struct pt_reg trap frames. */
 #define LOAD_PT_INS(base_reg) \
-        ldd     [%base_reg + REGWIN_SZ + PT_I0], %i0; \
-        ldd     [%base_reg + REGWIN_SZ + PT_I2], %i2; \
-        ldd     [%base_reg + REGWIN_SZ + PT_I4], %i4; \
-        ldd     [%base_reg + REGWIN_SZ + PT_I6], %i6;
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I0], %i0; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I2], %i2; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I4], %i4; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_I6], %i6;
 
 #define LOAD_PT_GLOBALS(base_reg) \
-        ld      [%base_reg + REGWIN_SZ + PT_G1], %g1; \
-        ldd     [%base_reg + REGWIN_SZ + PT_G2], %g2; \
-        ldd     [%base_reg + REGWIN_SZ + PT_G4], %g4; \
-        ldd     [%base_reg + REGWIN_SZ + PT_G6], %g6;
+        ld      [%base_reg + STACKFRAME_SZ + PT_G1], %g1; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_G2], %g2; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_G4], %g4; \
+        ldd     [%base_reg + STACKFRAME_SZ + PT_G6], %g6;
 
 #define LOAD_PT_YREG(base_reg, scratch) \
-        ld      [%base_reg + REGWIN_SZ + PT_Y], %scratch; \
+        ld      [%base_reg + STACKFRAME_SZ + PT_Y], %scratch; \
         wr      %scratch, 0x0, %y;
 
 #define LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
-        ld      [%base_reg + REGWIN_SZ + PT_PSR], %pt_psr; \
-        ld      [%base_reg + REGWIN_SZ + PT_PC], %pt_pc; \
-        ld      [%base_reg + REGWIN_SZ + PT_NPC], %pt_npc;
+        ld      [%base_reg + STACKFRAME_SZ + PT_PSR], %pt_psr; \
+        ld      [%base_reg + STACKFRAME_SZ + PT_PC], %pt_pc; \
+        ld      [%base_reg + STACKFRAME_SZ + PT_NPC], %pt_npc;
 
 #define LOAD_PT_ALL(base_reg, pt_psr, pt_pc, pt_npc, scratch) \
         LOAD_PT_YREG(base_reg, scratch) \
@@ -72,25 +64,25 @@
         LOAD_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc)
 
 #define STORE_PT_INS(base_reg) \
-        std     %i0, [%base_reg + REGWIN_SZ + PT_I0]; \
-        std     %i2, [%base_reg + REGWIN_SZ + PT_I2]; \
-        std     %i4, [%base_reg + REGWIN_SZ + PT_I4]; \
-        std     %i6, [%base_reg + REGWIN_SZ + PT_I6];
+        std     %i0, [%base_reg + STACKFRAME_SZ + PT_I0]; \
+        std     %i2, [%base_reg + STACKFRAME_SZ + PT_I2]; \
+        std     %i4, [%base_reg + STACKFRAME_SZ + PT_I4]; \
+        std     %i6, [%base_reg + STACKFRAME_SZ + PT_I6];
 
 #define STORE_PT_GLOBALS(base_reg) \
-        st      %g1, [%base_reg + REGWIN_SZ + PT_G1]; \
-        std     %g2, [%base_reg + REGWIN_SZ + PT_G2]; \
-        std     %g4, [%base_reg + REGWIN_SZ + PT_G4]; \
-        std     %g6, [%base_reg + REGWIN_SZ + PT_G6];
+        st      %g1, [%base_reg + STACKFRAME_SZ + PT_G1]; \
+        std     %g2, [%base_reg + STACKFRAME_SZ + PT_G2]; \
+        std     %g4, [%base_reg + STACKFRAME_SZ + PT_G4]; \
+        std     %g6, [%base_reg + STACKFRAME_SZ + PT_G6];
 
 #define STORE_PT_YREG(base_reg, scratch) \
         rd      %y, %scratch; \
-        st      %scratch, [%base_reg + REGWIN_SZ + PT_Y];
+        st      %scratch, [%base_reg + STACKFRAME_SZ + PT_Y];
 
 #define STORE_PT_PRIV(base_reg, pt_psr, pt_pc, pt_npc) \
-        st      %pt_psr, [%base_reg + REGWIN_SZ + PT_PSR]; \
-        st      %pt_pc,  [%base_reg + REGWIN_SZ + PT_PC]; \
-        st      %pt_npc, [%base_reg + REGWIN_SZ + PT_NPC];
+        st      %pt_psr, [%base_reg + STACKFRAME_SZ + PT_PSR]; \
+        st      %pt_pc,  [%base_reg + STACKFRAME_SZ + PT_PC]; \
+        st      %pt_npc, [%base_reg + STACKFRAME_SZ + PT_NPC];
 
 #define STORE_PT_ALL(base_reg, reg_psr, reg_pc, reg_npc, g_scratch) \
         STORE_PT_PRIV(base_reg, reg_psr, reg_pc, reg_npc) \
diff -urN linux-2.4.21-rc6/include/asm-sparc64/auxio.h linux-2.4.21-rc7/include/asm-sparc64/auxio.h
--- linux-2.4.21-rc6/include/asm-sparc64/auxio.h	2001-06-11 19:15:27.000000000 -0700
+++ linux-2.4.21-rc7/include/asm-sparc64/auxio.h	2003-06-03 10:06:05.000000000 -0700
@@ -1,112 +1,98 @@
 /* $Id: auxio.h,v 1.3 2001/06/05 08:16:34 davem Exp $
- * auxio.h:  Definitions and code for the Auxiliary I/O register.
+ * auxio.h:  Definitions and code for the Auxiliary I/O registers
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ *
+ * Refactoring for unified NCR/PCIO support 2002 Eric Brower (ebrower@usa.net)
  */
 #ifndef _SPARC64_AUXIO_H
 #define _SPARC64_AUXIO_H
 
-#include <asm/system.h>
-#include <asm/io.h>
-
-/* FIXME: All of this should be checked for sun4u. It has /sbus/auxio, but
-   I don't know whether it is the same and don't have a floppy */
+/* AUXIO implementations:
+ * sbus-based NCR89C105 "Slavio"
+ *	LED/Floppy (AUX1) register
+ *	Power (AUX2) register
+ *
+ * ebus-based auxio on PCIO 
+ *	LED Auxio Register
+ *	Power Auxio Register
+ *
+ * Register definitions from NCR _NCR89C105 Chip Specification_
+ * 
+ * SLAVIO AUX1 @ 0x1900000
+ * -------------------------------------------------
+ * | (R) | (R) |  D  | (R) |  E  |  M  |  T  |  L  |
+ * -------------------------------------------------
+ * (R) - bit 7:6,4 are reserved and should be masked in s/w
+ *  D  - Floppy Density Sense (1=high density) R/O
+ *  E  - Link Test Enable, directly reflected on AT&T 7213 LTE pin
+ *  M  - Monitor/Mouse Mux, directly reflected on MON_MSE_MUX pin
+ *  T  - Terminal Count: sends TC pulse to 82077 floppy controller
+ *  L  - System LED on front panel (0=off, 1=on) 
+ */
+#define AUXIO_AUX1_MASK		0xc0 /* Mask bits 		*/
+#define AUXIO_AUX1_FDENS	0x20 /* Floppy Density Sense	*/
+#define AUXIO_AUX1_LTE 		0x08 /* Link Test Enable 	*/
+#define AUXIO_AUX1_MMUX		0x04 /* Monitor/Mouse Mux	*/
+#define AUXIO_AUX1_FTCNT	0x02 /* Terminal Count, 	*/
+#define AUXIO_AUX1_LED		0x01 /* System LED		*/
+
+/* SLAVIO AUX2 @ 0x1910000
+ * -------------------------------------------------
+ * | (R) | (R) |  D  | (R) | (R) | (R) |  C  |  F  |
+ * -------------------------------------------------
+ * (R) - bits 7:6,4:2 are reserved and should be masked in s/w
+ *  D  - Power Failure Detect (1=power fail)
+ *  C  - Clear Power Failure Detect Int (1=clear)
+ *  F  - Power Off (1=power off)
+ */
+#define AUXIO_AUX2_MASK		0xdc /* Mask Bits		*/
+#define AUXIO_AUX2_PFAILDET	0x20 /* Power Fail Detect	*/
+#define AUXIO_AUX2_PFAILCLR 	0x02 /* Clear Pwr Fail Det Intr	*/
+#define AUXIO_AUX2_PWR_OFF	0x01 /* Power Off		*/
 
-extern unsigned long auxio_register;
+/* Register definitions from Sun Microsystems _PCIO_ p/n 802-7837
+ *
+ * PCIO LED Auxio @ 0x726000
+ * -------------------------------------------------
+ * |             31:1 Unused                 | LED |
+ * -------------------------------------------------
+ * Bits 31:1 unused
+ * LED - System LED on front panel (0=off, 1=on)
+ */
+#define AUXIO_PCIO_LED		0x01 /* System LED 		*/ 
 
-/* This register is an unsigned char in IO space.  It does two things.
- * First, it is used to control the front panel LED light on machines
- * that have it (good for testing entry points to trap handlers and irq's)
- * Secondly, it controls various floppy drive parameters.
- */
-#define AUXIO_ORMEIN      0xf0    /* All writes must set these bits. */
-#define AUXIO_ORMEIN4M    0xc0    /* sun4m - All writes must set these bits. */
-#define AUXIO_FLPY_DENS   0x20    /* Floppy density, high if set. Read only. */
-#define AUXIO_FLPY_DCHG   0x10    /* A disk change occurred.  Read only. */
-#define AUXIO_EDGE_ON     0x10    /* sun4m - On means Jumper block is in. */
-#define AUXIO_FLPY_DSEL   0x08    /* Drive select/start-motor. Write only. */
-#define AUXIO_LINK_TEST   0x08    /* sun4m - On means TPE Carrier detect. */
-
-/* Set the following to one, then zero, after doing a pseudo DMA transfer. */
-#define AUXIO_FLPY_TCNT   0x04    /* Floppy terminal count. Write only. */
-
-/* Set the following to zero to eject the floppy. */
-#define AUXIO_FLPY_EJCT   0x02    /* Eject floppy disk.  Write only. */
-#define AUXIO_LED         0x01    /* On if set, off if unset. Read/Write */
-
-#define AUXREG   (auxio_register)
-
-/* These are available on sun4c */
-#define TURN_ON_LED   \
-do {	if (AUXREG) \
-		sbus_writeb(sbus_readb(AUXREG) | \
-			    (AUXIO_ORMEIN | AUXIO_LED), AUXREG); \
-} while(0)
-#define TURN_OFF_LED  \
-do {	if (AUXREG) \
-		sbus_writeb((sbus_readb(AUXREG) | \
-			     AUXIO_ORMEIN) & (~AUXIO_LED), \
-			    AUXREG); \
-} while(0)
-#define FLIP_LED	\
-do {	if (AUXREG)  \
-		sbus_writeb((sbus_readb(AUXREG) | \
-			     AUXIO_ORMEIN) ^ AUXIO_LEN, \
-			    AUXREG); \
-} while(0)
-#define FLPY_MOTORON	\
-do {	if (AUXREG) \
-		sbus_writeb(sbus_readb(AUXREG) | \
-			    (AUXIO_ORMEIN | AUXIO_FLPY_DSEL), \
-			    AUXREG); \
-} while(0)
-#define FLPY_MOTOROFF	\
-do {	if (AUXREG) \
-		sbus_writeb((sbus_readb(AUXREG) | \
-			     AUXIO_ORMEIN) & (~AUXIO_FLPY_DSEL), \
-			    AUXREG); \
-} while(0)
-#define FLPY_TCNTON	\
-do {	if (AUXREG) \
-		sbus_writeb((sbus_readb(AUXREG) | \
-			     AUXIO_ORMEIN) | AUXIO_FLPY_TCNT, \
-			    AUXREG); \
-} while(0)
-#define FLPY_TCNTOFF	\
-do {	if (AUXREG) \
-		sbus_writeb((sbus_readb(AUXREG) | \
-			     AUXIO_ORMEIN) & (~AUXIO_FLPY_TCNT), \
-			    AUXREG); \
-} while(0)
+/* PCIO Power Auxio @ 0x724000
+ * -------------------------------------------------
+ * |             31:2 Unused           | CPO | SPO |
+ * -------------------------------------------------
+ * Bits 31:2 unused
+ * CPO - Courtesy Power Off (1=off)
+ * SPO - System Power Off   (1=off)
+ */
+#define AUXIO_PCIO_CPWR_OFF	0x02 /* Courtesy Power Off	*/
+#define AUXIO_PCIO_SPWR_OFF	0x01 /* System Power Off	*/
 
 #ifndef __ASSEMBLY__
-extern __inline__ void set_auxio(unsigned char bits_on, unsigned char bits_off)
-{
-	unsigned char regval;
-	unsigned long flags;
-
-	save_flags(flags); cli();
 
-	if(AUXREG) {
-		unsigned char newval;
-
-		regval = sbus_readb(AUXREG);
-		newval  = regval | bits_on;
-		newval &= ~bits_off;
-		newval |= AUXIO_ORMEIN4M;
-		sbus_writeb(newval, AUXREG);
-	}
-	restore_flags(flags);
-}
-#endif /* !(__ASSEMBLY__) */
+#define AUXIO_LTE_ON	1
+#define AUXIO_LTE_OFF	0
 
+/* auxio_set_lte - Set Link Test Enable (TPE Link Detect)
+ *
+ * on - AUXIO_LTE_ON or AUXIO_LTE_OFF
+ */
+extern void auxio_set_lte(int on);
 
-/* AUXIO2 (Power Off Control) */
-extern __volatile__ unsigned char * auxio_power_register;
+#define AUXIO_LED_ON	1
+#define AUXIO_LED_OFF	0
 
-#define	AUXIO_POWER_DETECT_FAILURE	32
-#define	AUXIO_POWER_CLEAR_FAILURE	2
-#define	AUXIO_POWER_OFF			1
+/* auxio_set_led - Set system front panel LED 
+ *
+ * on - AUXIO_LED_ON or AUXIO_LED_OFF
+ */
+extern void auxio_set_led(int on);
 
+#endif /* ifndef __ASSEMBLY__ */ 
 
-#endif /* !(_SPARC_AUXIO_H) */
+#endif /* !(_SPARC64_AUXIO_H) */
diff -urN linux-2.4.21-rc6/include/linux/sysctl.h linux-2.4.21-rc7/include/linux/sysctl.h
--- linux-2.4.21-rc6/include/linux/sysctl.h	2003-06-03 10:03:48.000000000 -0700
+++ linux-2.4.21-rc7/include/linux/sysctl.h	2003-06-03 10:06:06.000000000 -0700
@@ -295,7 +295,8 @@
 	NET_IPV4_ICMP_RATEMASK=90,
 	NET_TCP_TW_REUSE=91,
 	NET_TCP_FRTO=92,
-	NET_TCP_LOW_LATENCY=93
+	NET_TCP_LOW_LATENCY=93,
+	NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
 };
 
 enum {
diff -urN linux-2.4.21-rc6/include/net/transp_v6.h linux-2.4.21-rc7/include/net/transp_v6.h
--- linux-2.4.21-rc6/include/net/transp_v6.h	2001-11-22 11:47:58.000000000 -0800
+++ linux-2.4.21-rc7/include/net/transp_v6.h	2003-06-03 10:06:06.000000000 -0700
@@ -15,6 +15,8 @@
 
 struct flowi;
 
+extern void				ipv6_frag_init(void);
+
 extern void				rawv6_init(void);
 extern void				udpv6_init(void);
 extern void				tcpv6_init(void);
diff -urN linux-2.4.21-rc6/include/scsi/sg.h linux-2.4.21-rc7/include/scsi/sg.h
--- linux-2.4.21-rc6/include/scsi/sg.h	2002-11-28 15:53:15.000000000 -0800
+++ linux-2.4.21-rc7/include/scsi/sg.h	2003-06-03 10:06:06.000000000 -0700
@@ -9,11 +9,13 @@
 Original driver (sg.h):
 *       Copyright (C) 1992 Lawrence Foard
 Version 2 and 3 extensions to driver:
-*       Copyright (C) 1998 - 2002 Douglas Gilbert
+*       Copyright (C) 1998 - 2003 Douglas Gilbert
 
-    Version: 3.1.24 (20020505)
+    Version: 3.1.25 (20030529)
     This version is for 2.4 series kernels.
 
+    Changes since 3.1.24 (20020505)
+	- fix side effect introduced by last "off by one" fix
     Changes since 3.1.23 (20020318)
 	- off by one fix for last scatter gather element
 	- zero buffer obtained for non-root users
diff -urN linux-2.4.21-rc6/net/ipv4/af_inet.c linux-2.4.21-rc7/net/ipv4/af_inet.c
--- linux-2.4.21-rc6/net/ipv4/af_inet.c	2003-06-03 10:03:49.000000000 -0700
+++ linux-2.4.21-rc7/net/ipv4/af_inet.c	2003-06-03 10:06:08.000000000 -0700
@@ -1100,6 +1100,7 @@
 	}
 }
 
+extern void ipfrag_init(void);
 
 /*
  *	Called by socket.c on kernel startup.  
@@ -1196,6 +1197,9 @@
 	proc_net_create ("tcp", 0, tcp_get_info);
 	proc_net_create ("udp", 0, udp_get_info);
 #endif		/* CONFIG_PROC_FS */
+
+	ipfrag_init();
+
 	return 0;
 }
 module_init(inet_init);
diff -urN linux-2.4.21-rc6/net/ipv4/ip_fragment.c linux-2.4.21-rc7/net/ipv4/ip_fragment.c
--- linux-2.4.21-rc6/net/ipv4/ip_fragment.c	2003-06-03 10:03:49.000000000 -0700
+++ linux-2.4.21-rc7/net/ipv4/ip_fragment.c	2003-06-03 10:06:08.000000000 -0700
@@ -31,6 +31,8 @@
 #include <linux/ip.h>
 #include <linux/icmp.h>
 #include <linux/netdevice.h>
+#include <linux/jhash.h>
+#include <linux/random.h>
 #include <net/sock.h>
 #include <net/ip.h>
 #include <net/icmp.h>
@@ -97,6 +99,7 @@
 /* Per-bucket lock is easy to add now. */
 static struct ipq *ipq_hash[IPQ_HASHSZ];
 static rwlock_t ipfrag_lock = RW_LOCK_UNLOCKED;
+static u32 ipfrag_hash_rnd;
 static LIST_HEAD(ipq_lru_list);
 int ip_frag_nqueues = 0;
 
@@ -116,21 +119,51 @@
 	write_unlock(&ipfrag_lock);
 }
 
-/*
- * Was:	((((id) >> 1) ^ (saddr) ^ (daddr) ^ (prot)) & (IPQ_HASHSZ - 1))
- *
- * I see, I see evil hand of bigendian mafia. On Intel all the packets hit
- * one hash bucket with this hash function. 8)
- */
-static __inline__ unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
+static unsigned int ipqhashfn(u16 id, u32 saddr, u32 daddr, u8 prot)
 {
-	unsigned int h = saddr ^ daddr;
-
-	h ^= (h>>16)^id;
-	h ^= (h>>8)^prot;
-	return h & (IPQ_HASHSZ - 1);
+	return jhash_3words((u32)id << 16 | prot, saddr, daddr,
+			    ipfrag_hash_rnd) & (IPQ_HASHSZ - 1);
 }
 
+static struct timer_list ipfrag_secret_timer;
+int sysctl_ipfrag_secret_interval = 10 * 60 * HZ;
+
+static void ipfrag_secret_rebuild(unsigned long dummy)
+{
+	unsigned long now = jiffies;
+	int i;
+
+	write_lock(&ipfrag_lock);
+	get_random_bytes(&ipfrag_hash_rnd, sizeof(u32));
+	for (i = 0; i < IPQ_HASHSZ; i++) {
+		struct ipq *q;
+
+		q = ipq_hash[i];
+		while (q) {
+			struct ipq *next = q->next;
+			unsigned int hval = ipqhashfn(q->id, q->saddr,
+						      q->daddr, q->protocol);
+
+			if (hval != i) {
+				/* Unlink. */
+				if (q->next)
+					q->next->pprev = q->pprev;
+				*q->pprev = q->next;
+
+				/* Relink to new hash chain. */
+				if ((q->next = ipq_hash[hval]) != NULL)
+					q->next->pprev = &q->next;
+				ipq_hash[hval] = q;
+				q->pprev = &ipq_hash[hval];
+			}
+
+			q = next;
+		}
+	}
+	write_unlock(&ipfrag_lock);
+
+	mod_timer(&ipfrag_secret_timer, now + sysctl_ipfrag_secret_interval);
+}
 
 atomic_t ip_frag_mem = ATOMIC_INIT(0);	/* Memory used for fragments */
 
@@ -631,3 +664,14 @@
 	kfree_skb(skb);
 	return NULL;
 }
+
+void ipfrag_init(void)
+{
+	ipfrag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
+				 (jiffies ^ (jiffies >> 6)));
+
+	init_timer(&ipfrag_secret_timer);
+	ipfrag_secret_timer.function = ipfrag_secret_rebuild;
+	ipfrag_secret_timer.expires = jiffies + sysctl_ipfrag_secret_interval;
+	add_timer(&ipfrag_secret_timer);
+}
diff -urN linux-2.4.21-rc6/net/ipv4/sysctl_net_ipv4.c linux-2.4.21-rc7/net/ipv4/sysctl_net_ipv4.c
--- linux-2.4.21-rc6/net/ipv4/sysctl_net_ipv4.c	2003-06-03 10:03:50.000000000 -0700
+++ linux-2.4.21-rc7/net/ipv4/sysctl_net_ipv4.c	2003-06-03 10:06:09.000000000 -0700
@@ -27,6 +27,7 @@
 extern int sysctl_ipfrag_low_thresh;
 extern int sysctl_ipfrag_high_thresh; 
 extern int sysctl_ipfrag_time;
+extern int sysctl_ipfrag_secret_interval;
 
 /* From ip_output.c */
 extern int sysctl_ip_dynaddr;
@@ -225,6 +226,9 @@
 	 &sysctl_tcp_frto, sizeof(int), 0644, NULL, &proc_dointvec},
 	{NET_TCP_LOW_LATENCY, "tcp_low_latency",
 	 &sysctl_tcp_low_latency, sizeof(int), 0644, NULL, &proc_dointvec},
+	{NET_IPV4_IPFRAG_SECRET_INTERVAL, "ipfrag_secret_interval",
+	 &sysctl_ipfrag_secret_interval, sizeof(int), 0644, NULL, &proc_dointvec_jiffies, 
+	 &sysctl_jiffies},
 	{0}
 };
 
diff -urN linux-2.4.21-rc6/net/ipv6/af_inet6.c linux-2.4.21-rc7/net/ipv6/af_inet6.c
--- linux-2.4.21-rc6/net/ipv6/af_inet6.c	2003-06-03 10:03:50.000000000 -0700
+++ linux-2.4.21-rc7/net/ipv6/af_inet6.c	2003-06-03 10:06:09.000000000 -0700
@@ -671,6 +671,7 @@
 	ip6_flowlabel_init();
 	addrconf_init();
 	sit_init();
+	ipv6_frag_init();
 
 	/* Init v6 transport protocols. */
 	udpv6_init();
diff -urN linux-2.4.21-rc6/net/ipv6/reassembly.c linux-2.4.21-rc7/net/ipv6/reassembly.c
--- linux-2.4.21-rc6/net/ipv6/reassembly.c	2003-06-03 10:03:50.000000000 -0700
+++ linux-2.4.21-rc7/net/ipv6/reassembly.c	2003-06-03 10:06:10.000000000 -0700
@@ -37,6 +37,8 @@
 #include <linux/in6.h>
 #include <linux/ipv6.h>
 #include <linux/icmpv6.h>
+#include <linux/random.h>
+#include <linux/jhash.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -98,6 +100,7 @@
 
 static struct frag_queue *ip6_frag_hash[IP6Q_HASHSZ];
 static rwlock_t ip6_frag_lock = RW_LOCK_UNLOCKED;
+static u32 ip6_frag_hash_rnd;
 static LIST_HEAD(ip6_frag_lru_list);
 int ip6_frag_nqueues = 0;
 
@@ -117,16 +120,73 @@
 	write_unlock(&ip6_frag_lock);
 }
 
-static __inline__ unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
-					  struct in6_addr *daddr)
+static unsigned int ip6qhashfn(u32 id, struct in6_addr *saddr,
+			       struct in6_addr *daddr)
 {
-	unsigned int h = saddr->s6_addr32[3] ^ daddr->s6_addr32[3] ^ id;
+	u32 a, b, c;
 
-	h ^= (h>>16);
-	h ^= (h>>8);
-	return h & (IP6Q_HASHSZ - 1);
+	a = saddr->s6_addr32[0];
+	b = saddr->s6_addr32[1];
+	c = saddr->s6_addr32[2];
+
+	a += JHASH_GOLDEN_RATIO;
+	b += JHASH_GOLDEN_RATIO;
+	c += ip6_frag_hash_rnd;
+	__jhash_mix(a, b, c);
+
+	a += saddr->s6_addr32[3];
+	b += daddr->s6_addr32[0];
+	c += daddr->s6_addr32[1];
+	__jhash_mix(a, b, c);
+
+	a += daddr->s6_addr32[2];
+	b += daddr->s6_addr32[3];
+	c += id;
+	__jhash_mix(a, b, c);
+
+	return c & (IP6Q_HASHSZ - 1);
 }
 
+static struct timer_list ip6_frag_secret_timer;
+static int ip6_frag_secret_interval = 10 * 60 * HZ;
+
+static void ip6_frag_secret_rebuild(unsigned long dummy)
+{
+	unsigned long now = jiffies;
+	int i;
+
+	write_lock(&ip6_frag_lock);
+	get_random_bytes(&ip6_frag_hash_rnd, sizeof(u32));
+	for (i = 0; i < IP6Q_HASHSZ; i++) {
+		struct frag_queue *q;
+
+		q = ip6_frag_hash[i];
+		while (q) {
+			struct frag_queue *next = q->next;
+			unsigned int hval = ip6qhashfn(q->id,
+						       &q->saddr,
+						       &q->daddr);
+
+			if (hval != i) {
+				/* Unlink. */
+				if (q->next)
+					q->next->pprev = q->pprev;
+				*q->pprev = q->next;
+
+				/* Relink to new hash chain. */
+				if ((q->next = ip6_frag_hash[hval]) != NULL)
+					q->next->pprev = &q->next;
+				ip6_frag_hash[hval] = q;
+				q->pprev = &ip6_frag_hash[hval];
+			}
+
+			q = next;
+		}
+	}
+	write_unlock(&ip6_frag_lock);
+
+	mod_timer(&ip6_frag_secret_timer, now + ip6_frag_secret_interval);
+}
 
 atomic_t ip6_frag_mem = ATOMIC_INIT(0);
 
@@ -681,3 +741,14 @@
 	kfree_skb(skb);
 	return -1;
 }
+
+void __init ipv6_frag_init(void)
+{
+	ip6_frag_hash_rnd = (u32) ((num_physpages ^ (num_physpages>>7)) ^
+				   (jiffies ^ (jiffies >> 6)));
+
+	init_timer(&ip6_frag_secret_timer);
+	ip6_frag_secret_timer.function = ip6_frag_secret_rebuild;
+	ip6_frag_secret_timer.expires = jiffies + ip6_frag_secret_interval;
+	add_timer(&ip6_frag_secret_timer);
+}
diff -urN linux-2.4.21-rc6/net/ipv6/tcp_ipv6.c linux-2.4.21-rc7/net/ipv6/tcp_ipv6.c
--- linux-2.4.21-rc6/net/ipv6/tcp_ipv6.c	2003-06-03 10:03:50.000000000 -0700
+++ linux-2.4.21-rc7/net/ipv6/tcp_ipv6.c	2003-06-03 10:06:10.000000000 -0700
@@ -371,9 +371,22 @@
 
 static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
 {
-	return (jhash_3words(raddr->s6_addr32[0] ^ raddr->s6_addr32[1],
-	                     raddr->s6_addr32[2] ^ raddr->s6_addr32[3],
-	                     (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1));
+	u32 a, b, c;
+
+	a = raddr->s6_addr32[0];
+	b = raddr->s6_addr32[1];
+	c = raddr->s6_addr32[2];
+
+	a += JHASH_GOLDEN_RATIO;
+	b += JHASH_GOLDEN_RATIO;
+	c += rnd;
+	__jhash_mix(a, b, c);
+
+	a += raddr->s6_addr32[3];
+	b += (u32) rport;
+	__jhash_mix(a, b, c);
+
+	return c & (TCP_SYNQ_HSIZE - 1);
 }
 
 static struct open_request *tcp_v6_search_req(struct tcp_opt *tp,
