Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6:
  [IA64] Quicklist support for IA64
  [IA64] fix Kprobes reentrancy
  [IA64] SN: validate smp_affinity mask on intr redirect
  [IA64] drivers/char/snsc_event.c:206: warning: unused variable `p'
  [IA64] mca.c:121: warning: 'cpe_poll_timer' defined but not used
  [IA64] Fix - Section mismatch: reference to .init.data:mvec_name
  [IA64] more warning cleanups
  [IA64] Wire up epoll_pwait and utimensat
  [IA64] Fix warnings resulting from type-checking in dev_dbg()
  [IA64] typo s/kenrel/kernel/
diff --git a/CREDITS b/CREDITS
index 6829e91..273d72b 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2299,8 +2299,8 @@
 W: http://oops.ghostprotocols.net:81/blog/
 P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
 D: IPX, LLC, DCCP, cyc2x, wl3501_cs, net/ hacks
-S: R. Brasílio Itiberê, 4270/1010 - Água Verde
-S: 80240-060 - Curitiba - Paraná
+S: R. Brasílio Itiberê, 4270/1010 - Água Verde
+S: 80240-060 - Curitiba - Paraná
 S: Brazil
 
 N: Karsten Merker
diff --git a/Documentation/SubmitChecklist b/Documentation/SubmitChecklist
index 6491b2c..3af3e65 100644
--- a/Documentation/SubmitChecklist
+++ b/Documentation/SubmitChecklist
@@ -73,9 +73,9 @@
     If the new code is substantial, addition of subsystem-specific fault
     injection might be appropriate.
 
-22: Newly-added code has been compiled with `gcc -W'.  This will generate
-    lots of noise, but is good for finding bugs like "warning: comparison
-    between signed and unsigned".
+22: Newly-added code has been compiled with `gcc -W' (use "make
+    EXTRA_CFLAGS=-W").  This will generate lots of noise, but is good for
+    finding bugs like "warning: comparison between signed and unsigned".
 
 23: Tested after it has been merged into the -mm patchset to make sure
     that it still works with all of the other queued patches and various
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 676b798..c6322c7 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -278,14 +278,6 @@
 
 ---------------------------
 
-What:	i8xx_tco watchdog driver
-When:	in 2.6.22
-Why:	the i8xx_tco watchdog driver has been replaced by the iTCO_wdt
-	watchdog driver.
-Who:	Wim Van Sebroeck <wim@iguana.be>
-
----------------------------
-
 What:	Multipath cached routing support in ipv4
 When:	in 2.6.23
 Why:	Code was merged, then submitter immediately disappeared leaving
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index f8528db..e8be0ab 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -66,7 +66,9 @@
 used for several very different kinds of GPIO controller.
 
 That said, if the convention is supported on their platform, drivers should
-use it when possible:
+use it when possible.  Platforms should declare GENERIC_GPIO support in
+Kconfig (boolean true), which multi-platform drivers can depend on when
+using the include file:
 
 	#include <asm/gpio.h>
 
diff --git a/Documentation/kref.txt b/Documentation/kref.txt
index 42fe284..f38b59d 100644
--- a/Documentation/kref.txt
+++ b/Documentation/kref.txt
@@ -67,7 +67,7 @@
 	.
 	. do stuff with data here
 	.
-	kref_put(data, data_release);
+	kref_put(&data->refcount, data_release);
 }
 
 int my_data_handler(void)
diff --git a/Documentation/mips/pci/pci.README b/Documentation/mips/pci/pci.README
deleted file mode 100644
index 8697ee4..0000000
--- a/Documentation/mips/pci/pci.README
+++ /dev/null
@@ -1,54 +0,0 @@
-
-Pete Popov, ppopov@pacbell.net
-07/11/2001
-
-This README briefly explains how to use the pci and pci_auto
-code in arch/mips/kernel.  The code was ported from PowerPC and
-modified slightly. It has been tested pretty well on PPC on some
-rather complex systems with multiple bridges and devices behind
-each bridge. However, at the time this README was written, the
-mips port was tested only on boards with a single pci bus and
-no P2P bridges.  It's very possible that on boards with P2P
-bridges some modifications have to be made. The code will 
-evolve, no doubt, but currently every single mips board
-is doing its own pcibios thing and it has become a big
-mess.  This generic pci code is meant to clean up the mips
-pci mess and make it easier to add pci support to new boards.
-
-inside the define for your board in arch/mips/config.in. 
-For example, the Galileo EV96100 board  looks like this:
-
-if [ "$CONFIG_MIPS_EV96100" = "y" ]; then
-	define_bool CONFIG_PCI y
-	define_bool CONFIG_MIPS_GT96100 y
-	define_bool CONFIG_NEW_PCI y
-	define_bool CONFIG_SWAP_IO_SPACE y
-fi 
-
-
-Next, if you want to use the arch/mips/kernel/pci code, which has the
-pcibios_init() function, add
-
-define_bool CONFIG_NEW_PCI y
- 
-inside the define for your board. Again, the EV96100 example above
-show NEW_PCI turned on.
-
-
-Now you need to add your files to hook in your pci configuration
-cycles.  Usually you'll need only a couple of files named something
-like pci_fixups.c and pci_ops.c.  You can copy the templates
-provided and fill in the code.
-
-The file pci_ops.c should contain the pci configuration cycles routines.
-It also has the mips_pci_channels[] array which contains the descriptors
-of each pci controller.
-
-The file pci_fixups.c contains a few routines to do interrupt fixups,
-resources fixups, and, if needed, pci bios fixups.
-
-Usually you'll put your pci_fixups.c file in your board specific directory, 
-since the functions in that file are board specific.  The functions in
-pci_ops.c, on the other hand, are usually pci controller specific so that
-file could be shared among a few different boards using the same
-pci controller.
diff --git a/MAINTAINERS b/MAINTAINERS
index cfd26dd..bd558ac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1718,12 +1718,6 @@
 M:	hpa@zytor.com
 S:	Maintained
 
-i810 TCO TIMER WATCHDOG
-P:	Nils Faerber
-M:	nils@kernelconcepts.de
-W:	http://www.kernelconcepts.de/
-S:	Maintained
-
 IA64 (Itanium) PLATFORM
 P:	Tony Luck
 M:	tony.luck@intel.com
diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
index 9550f37..1e7a101 100644
--- a/arch/frv/kernel/gdb-stub.c
+++ b/arch/frv/kernel/gdb-stub.c
@@ -1195,7 +1195,7 @@
 /*
  *
  */
-static void __attribute__((unused)) gdbstub_show_regs(void)
+static void __maybe_unused gdbstub_show_regs(void)
 {
 	unsigned long *reg;
 	int loop;
@@ -1223,7 +1223,7 @@
 /*
  * dump debugging regs
  */
-static void __attribute__((unused)) gdbstub_dump_debugregs(void)
+static void __maybe_unused gdbstub_dump_debugregs(void)
 {
 	gdbstub_printk("DCR    %08lx  ", __debug_status.dcr);
 	gdbstub_printk("BRR    %08lx\n", __debug_status.brr);
@@ -2079,25 +2079,25 @@
  * GDB wants to call malloc() and free() to allocate memory for calling kernel
  * functions directly from its command line
  */
-static void *malloc(size_t size) __attribute__((unused));
+static void *malloc(size_t size) __maybe_unused;
 static void *malloc(size_t size)
 {
 	return kmalloc(size, GFP_ATOMIC);
 }
 
-static void free(void *p) __attribute__((unused));
+static void free(void *p) __maybe_unused;
 static void free(void *p)
 {
 	kfree(p);
 }
 
-static uint32_t ___get_HSR0(void) __attribute__((unused));
+static uint32_t ___get_HSR0(void) __maybe_unused;
 static uint32_t ___get_HSR0(void)
 {
 	return __get_HSR(0);
 }
 
-static uint32_t ___set_HSR0(uint32_t x) __attribute__((unused));
+static uint32_t ___set_HSR0(uint32_t x) __maybe_unused;
 static uint32_t ___set_HSR0(uint32_t x)
 {
 	__set_HSR(0, x);
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index dab98fd..54e21c3 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -31,7 +31,7 @@
 	.long SYMBOL_NAME(sys_mknod)
 	.long SYMBOL_NAME(sys_chmod)		/* 15 */
 	.long SYMBOL_NAME(sys_chown16)
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old break syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old break syscall holder */
 	.long SYMBOL_NAME(sys_stat)
 	.long SYMBOL_NAME(sys_lseek)
 	.long SYMBOL_NAME(sys_getpid)		/* 20 */
@@ -45,11 +45,11 @@
 	.long SYMBOL_NAME(sys_fstat)
 	.long SYMBOL_NAME(sys_pause)
 	.long SYMBOL_NAME(sys_utime)		/* 30 */
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old stty syscall holder */
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old gtty syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old stty syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old gtty syscall holder */
 	.long SYMBOL_NAME(sys_access)
 	.long SYMBOL_NAME(sys_nice)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* 35 */		/* old ftime syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 35 old ftime syscall holder */
 	.long SYMBOL_NAME(sys_sync)
 	.long SYMBOL_NAME(sys_kill)
 	.long SYMBOL_NAME(sys_rename)
@@ -58,7 +58,7 @@
 	.long SYMBOL_NAME(sys_dup)
 	.long SYMBOL_NAME(sys_pipe)
 	.long SYMBOL_NAME(sys_times)
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old prof syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old prof syscall holder */
 	.long SYMBOL_NAME(sys_brk)		/* 45 */
 	.long SYMBOL_NAME(sys_setgid16)
 	.long SYMBOL_NAME(sys_getgid16)
@@ -66,13 +66,13 @@
 	.long SYMBOL_NAME(sys_geteuid16)
 	.long SYMBOL_NAME(sys_getegid16)	/* 50 */
 	.long SYMBOL_NAME(sys_acct)
-	.long SYMBOL_NAME(sys_umount)					/* recycled never used phys() */
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old lock syscall holder */
+	.long SYMBOL_NAME(sys_umount)		/* recycled never used phys() */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old lock syscall holder */
 	.long SYMBOL_NAME(sys_ioctl)
 	.long SYMBOL_NAME(sys_fcntl)		/* 55 */
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old mpx syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old mpx syscall holder */
 	.long SYMBOL_NAME(sys_setpgid)
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old ulimit syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old ulimit syscall holder */
 	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_umask)		/* 60 */
 	.long SYMBOL_NAME(sys_chroot)
@@ -112,7 +112,7 @@
 	.long SYMBOL_NAME(sys_fchown16)		/* 95 */
 	.long SYMBOL_NAME(sys_getpriority)
 	.long SYMBOL_NAME(sys_setpriority)
-	.long SYMBOL_NAME(sys_ni_syscall)				/* old profil syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old profil syscall holder */
 	.long SYMBOL_NAME(sys_statfs)
 	.long SYMBOL_NAME(sys_fstatfs)		/* 100 */
 	.long SYMBOL_NAME(sys_ni_syscall)	/* ioperm for i386 */
@@ -202,8 +202,8 @@
 	.long SYMBOL_NAME(sys_capset)           /* 185 */
 	.long SYMBOL_NAME(sys_sigaltstack)
 	.long SYMBOL_NAME(sys_sendfile)
-	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
-	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* streams1 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* streams2 */
 	.long SYMBOL_NAME(sys_vfork)            /* 190 */
 	.long SYMBOL_NAME(sys_getrlimit)
 	.long SYMBOL_NAME(sys_mmap2)
@@ -236,10 +236,10 @@
 	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_getdents64)	/* 220 */
 	.long SYMBOL_NAME(sys_fcntl64)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for TUX */
-	.long SYMBOL_NAME(sys_ni_syscall)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved TUX */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved Security */
 	.long SYMBOL_NAME(sys_gettid)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* 225 */ /* sys_readahead */
+	.long SYMBOL_NAME(sys_readahead)	/* 225 */
 	.long SYMBOL_NAME(sys_setxattr)
 	.long SYMBOL_NAME(sys_lsetxattr)
 	.long SYMBOL_NAME(sys_fsetxattr)
@@ -257,8 +257,8 @@
 	.long SYMBOL_NAME(sys_futex)		/* 240 */
 	.long SYMBOL_NAME(sys_sched_setaffinity)
 	.long SYMBOL_NAME(sys_sched_getaffinity)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_set_thread_area */
-	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_get_thread_area */
+	.long SYMBOL_NAME(sys_ni_syscall)
+	.long SYMBOL_NAME(sys_ni_syscall)
 	.long SYMBOL_NAME(sys_io_setup)		/* 245 */
 	.long SYMBOL_NAME(sys_io_destroy)
 	.long SYMBOL_NAME(sys_io_getevents)
@@ -288,8 +288,8 @@
 	.long SYMBOL_NAME(sys_utimes)
  	.long SYMBOL_NAME(sys_fadvise64_64)
 	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_vserver */
-	.long SYMBOL_NAME(sys_mbind)
-	.long SYMBOL_NAME(sys_get_mempolicy)
+	.long SYMBOL_NAME(sys_ni_syscall)
+	.long SYMBOL_NAME(sys_get_mempolicy)	/* 275 */
 	.long SYMBOL_NAME(sys_set_mempolicy)
 	.long SYMBOL_NAME(sys_mq_open)
 	.long SYMBOL_NAME(sys_mq_unlink)
@@ -297,16 +297,42 @@
 	.long SYMBOL_NAME(sys_mq_timedreceive)	/* 280 */
 	.long SYMBOL_NAME(sys_mq_notify)
 	.long SYMBOL_NAME(sys_mq_getsetattr)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* reserved for kexec */
 	.long SYMBOL_NAME(sys_waitid)
-	.long SYMBOL_NAME(sys_ni_syscall)	/* 285 */ /* available */
-	.long SYMBOL_NAME(sys_add_key)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_kexec_load */
+	.long SYMBOL_NAME(sys_add_key) 		/* 285 */
 	.long SYMBOL_NAME(sys_request_key)
 	.long SYMBOL_NAME(sys_keyctl)
-
-	.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
-		.long SYMBOL_NAME(sys_ni_syscall)
-	.endr
+	.long SYMBOL_NAME(sys_ioprio_set)
+	.long SYMBOL_NAME(sys_ioprio_get)	/* 290 */
+	.long SYMBOL_NAME(sys_inotify_init)
+	.long SYMBOL_NAME(sys_inotify_add_watch)
+	.long SYMBOL_NAME(sys_inotify_rm_watch)
+	.long SYMBOL_NAME(sys_migrate_pages)
+	.long SYMBOL_NAME(sys_openat)		/* 295 */
+	.long SYMBOL_NAME(sys_mkdirat)
+	.long SYMBOL_NAME(sys_mknodat)
+	.long SYMBOL_NAME(sys_fchownat)
+	.long SYMBOL_NAME(sys_futimesat)
+	.long SYMBOL_NAME(sys_fstatat64)	/* 300 */
+	.long SYMBOL_NAME(sys_unlinkat)
+	.long SYMBOL_NAME(sys_renameat)
+	.long SYMBOL_NAME(sys_linkat)
+	.long SYMBOL_NAME(sys_symlinkat)
+	.long SYMBOL_NAME(sys_readlinkat)	/* 305 */
+	.long SYMBOL_NAME(sys_fchmodat)
+	.long SYMBOL_NAME(sys_faccessat)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_pselect6 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_ppoll */
+	.long SYMBOL_NAME(sys_unshare)		/* 310 */
+	.long SYMBOL_NAME(sys_set_robust_list)
+	.long SYMBOL_NAME(sys_get_robust_list)
+	.long SYMBOL_NAME(sys_splice)
+	.long SYMBOL_NAME(sys_sync_file_range)
+	.long SYMBOL_NAME(sys_tee)		/* 315 */
+	.long SYMBOL_NAME(sys_vmsplice)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_move_pages */
+	.long SYMBOL_NAME(sys_getcpu)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_epoll_pwait */
 
 	.macro	call_sp addr
 	mov.l	#SYMBOL_NAME(\addr),er6
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index 9b10af6..f74dfc4 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -71,12 +71,6 @@
 .section .text.head,"ax",@progbits
 ENTRY(startup_32)
 
-#ifdef CONFIG_PARAVIRT
-        movl %cs, %eax
-        testl $0x3, %eax
-        jnz startup_paravirt
-#endif
-
 /*
  * Set segments to known values.
  */
@@ -501,38 +495,6 @@
 	iret
 
 .section .text
-#ifdef CONFIG_PARAVIRT
-startup_paravirt:
-	cld
- 	movl $(init_thread_union+THREAD_SIZE),%esp
-
-	/* We take pains to preserve all the regs. */
-	pushl	%edx
-	pushl	%ecx
-	pushl	%eax
-
-	pushl	$__start_paravirtprobe
-1:
-	movl	0(%esp), %eax
-	cmpl	$__stop_paravirtprobe, %eax
-	je	unhandled_paravirt
-	pushl	(%eax)
-	movl	8(%esp), %eax
-	call	*(%esp)
-	popl	%eax
-
-	movl	4(%esp), %eax
-	movl	8(%esp), %ecx
-	movl	12(%esp), %edx
-
-	addl	$4, (%esp)
-	jmp	1b
-
-unhandled_paravirt:
-	/* Nothing wanted us: we're screwed. */
-	ud2
-#endif
-
 /*
  * Real beginning of normal "text" segment
  */
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c
index 5c10f37..faab09a 100644
--- a/arch/i386/kernel/paravirt.c
+++ b/arch/i386/kernel/paravirt.c
@@ -19,7 +19,6 @@
 #include <linux/module.h>
 #include <linux/efi.h>
 #include <linux/bcd.h>
-#include <linux/start_kernel.h>
 #include <linux/highmem.h>
 
 #include <asm/bug.h>
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 0772678..bf6adce 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -320,3 +320,6 @@
 	.long sys_getcpu
 	.long sys_epoll_pwait
 	.long sys_utimensat		/* 320 */
+	.long sys_signalfd
+	.long sys_timerfd
+	.long sys_eventfd
diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S
index e51a869..b2a9d80 100644
--- a/arch/i386/kernel/verify_cpu.S
+++ b/arch/i386/kernel/verify_cpu.S
@@ -10,7 +10,9 @@
 
 #if CONFIG_X86_MINIMUM_CPU_MODEL >= 4
 	pushfl
-	orl	$(1<<18),(%esp)		# try setting AC
+	pop	%eax
+	orl	$(1<<18),%eax		# try setting AC
+	push	%eax
 	popfl
 	pushfl
 	popl    %eax
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index 23e8614..80bec66 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -78,12 +78,6 @@
 	CONSTRUCTORS
 	} :data
 
-  .paravirtprobe : AT(ADDR(.paravirtprobe) - LOAD_OFFSET) {
-  	__start_paravirtprobe = .;
-	*(.paravirtprobe)
-  	__stop_paravirtprobe = .;
-  }
-
   . = ALIGN(4096);
   .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) {
   	__nosave_begin = .;
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
index 92d7d0c..8850fe4 100644
--- a/arch/ia64/ia32/audit.c
+++ b/arch/ia64/ia32/audit.c
@@ -20,6 +20,11 @@
 ~0U
 };
 
+unsigned ia32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int ia32_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
index 0468255..f3802ae 100644
--- a/arch/ia64/kernel/audit.c
+++ b/arch/ia64/kernel/audit.c
@@ -23,6 +23,20 @@
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_IA32_SUPPORT
+	if (arch == AUDIT_ARCH_I386)
+		return 1;
+#endif
+	return 0;
+}
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_IA32_SUPPORT
@@ -49,15 +63,18 @@
 	extern __u32 ia32_write_class[];
 	extern __u32 ia32_read_class[];
 	extern __u32 ia32_chattr_class[];
+	extern __u32 ia32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 9740d6b..c3bb8a75 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -241,6 +241,10 @@
 	bool
 	default y
 
+config SCHED_NO_NO_OMIT_FRAME_POINTER
+        bool
+        default y
+
 config PREEMPT
 	bool "Preemptible Kernel"
 	help
diff --git a/arch/m32r/mm/mmu.S b/arch/m32r/mm/mmu.S
index 8bb74b1..49a6d16 100644
--- a/arch/m32r/mm/mmu.S
+++ b/arch/m32r/mm/mmu.S
@@ -163,7 +163,8 @@
 
 	; pte_data = (unsigned long)pte_val(*pte);
 	ld	r2, @r3			; r2: pte data
-	or3	r2, r2, #2		; _PAGE_PRESENT(=2)
+	and3	r3, r2, #2		; _PAGE_PRESENT(=2) check
+	beqz	r3, 3f
 
 	.fillinsn
 5:
@@ -264,11 +265,8 @@
 ;
 	and3	r1, r1, #0xeff
 	ldi	r4, #611		; _KERNPG_TABLE(=611)
-	beq	r1, r4, 4f		; !pmd_bad(*pmd) ?
-	.fillinsn
-3:
-	ldi	r1, #0			; r1: pte_data = 0
-	bra	5f
+	bne	r1, r4, 3f		; !pmd_bad(*pmd) ?
+
 	.fillinsn
 4:
 	; pte = pte_offset(pmd, address);
@@ -282,8 +280,10 @@
 	add	r4, r3			; r4: pte
 	; pte_data = (unsigned long)pte_val(*pte);
 	ld	r1, @r4			; r1: pte_data
-	.fillinsn
+	and3	r3, r1, #2		; _PAGE_PRESENT(=2) check
+	beqz	r3, 3f
 
+	.fillinsn
 ;; set tlb
 ; r0: address, r1: pte_data, r2: entry
 ; r3,r4: (free)
@@ -295,8 +295,7 @@
 	and3	r4, r4, #(MMU_CONTEXT_ASID_MASK)
 	or	r3, r4
 	st	r3, @r2
-	or3	r4, r1, #2		; _PAGE_PRESENT(=2)
-	st	r4, @(4,r2)		; set_tlb_data(entry, pte_data);
+	st	r1, @(4,r2)		; set_tlb_data(entry, pte_data);
 
 	ld	r4, @sp+
 	ld	r3, @sp+
@@ -306,6 +305,11 @@
 	ld	sp, @sp+
 	rte
 
+	.fillinsn
+3:
+	ldi	r1, #2			; r1: pte_data = 0 | _PAGE_PRESENT(=2)
+	bra	5b
+
 #else
 #error unknown isa configuration
 #endif
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 16ecea3..0f09412 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -15,121 +15,8 @@
 	prompt "System type"
 	default SGI_IP22
 
-config MIPS_MTX1
-	bool "4G Systems MTX-1 board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select RESOURCES_64BIT if PCI
-	select SOC_AU1500
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_BOSPORUS
-	bool "AMD Alchemy Bosporus board"
-	select SOC_AU1500
-	select DMA_NONCOHERENT
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1000
-	bool "AMD Alchemy PB1000 board"
-	select SOC_AU1000
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select RESOURCES_64BIT if PCI
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1100
-	bool "AMD Alchemy PB1100 board"
-	select SOC_AU1100
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select RESOURCES_64BIT if PCI
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1500
-	bool "AMD Alchemy PB1500 board"
-	select SOC_AU1500
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select RESOURCES_64BIT if PCI
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1550
-	bool "AMD Alchemy PB1550 board"
-	select SOC_AU1550
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select MIPS_DISABLE_OBSOLETE_IDE
-	select RESOURCES_64BIT if PCI
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_PB1200
-	bool "AMD Alchemy PB1200 board"
-	select SOC_AU1200
-	select DMA_NONCOHERENT
-	select MIPS_DISABLE_OBSOLETE_IDE
-	select RESOURCES_64BIT if PCI
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1000
-	bool "AMD Alchemy DB1000 board"
-	select SOC_AU1000
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select RESOURCES_64BIT if PCI
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1100
-	bool "AMD Alchemy DB1100 board"
-	select SOC_AU1100
-	select DMA_NONCOHERENT
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1500
-	bool "AMD Alchemy DB1500 board"
-	select SOC_AU1500
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select MIPS_DISABLE_OBSOLETE_IDE
-	select RESOURCES_64BIT if PCI
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1550
-	bool "AMD Alchemy DB1550 board"
-	select SOC_AU1550
-	select HW_HAS_PCI
-	select DMA_NONCOHERENT
-	select MIPS_DISABLE_OBSOLETE_IDE
-	select RESOURCES_64BIT if PCI
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_DB1200
-	bool "AMD Alchemy DB1200 board"
-	select SOC_AU1200
-	select DMA_COHERENT
-	select MIPS_DISABLE_OBSOLETE_IDE
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
-config MIPS_MIRAGE
-	bool "AMD Alchemy Mirage board"
-	select DMA_NONCOHERENT
-	select SOC_AU1500
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_LITTLE_ENDIAN
+config MACH_ALCHEMY
+	bool "Alchemy processor based machines"
 
 config BASLER_EXCITE
 	bool "Basler eXcite smart camera"
@@ -369,28 +256,6 @@
 	  This option enables support for MIPS Technologies MIPSsim software
 	  emulator.
 
-config MOMENCO_JAGUAR_ATX
-	bool "Momentum Jaguar board"
-	select BOOT_ELF32
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select IRQ_MV64340
-	select LIMITED_DMA
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_RM9000
-	select SYS_HAS_EARLY_PRINTK
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL
-	select SYS_SUPPORTS_BIG_ENDIAN
-	select SYS_SUPPORTS_KGDB
-	help
-	  The Jaguar ATX is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
 config MOMENCO_OCELOT
 	bool "Momentum Ocelot board"
 	select DMA_NONCOHERENT
@@ -446,29 +311,6 @@
 	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
 	  Momentum Computer <http://www.momenco.com/>.
 
-config MOMENCO_OCELOT_G
-	bool "Momentum Ocelot-G board"
-	select DMA_NONCOHERENT
-	select HW_HAS_PCI
-	select IRQ_CPU
-	select IRQ_CPU_RM7K
-	select PCI_MARVELL
-	select RM7000_CPU_SCACHE
-	select SWAP_IO_SPACE
-	select SYS_HAS_CPU_RM7000
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_64BIT_KERNEL if BROKEN
-	select SYS_SUPPORTS_BIG_ENDIAN
-	help
-	  The Ocelot is a MIPS-based Single Board Computer (SBC) made by
-	  Momentum Computer <http://www.momenco.com/>.
-
-config MIPS_XXS1500
-	bool "MyCable XXS1500 board"
-	select DMA_NONCOHERENT
-	select SOC_AU1500
-	select SYS_SUPPORTS_LITTLE_ENDIAN
-
 config PNX8550_JBS
 	bool "Philips PNX8550 based JBS board"
 	select PNX8550
@@ -775,7 +617,6 @@
 	select SYS_SUPPORTS_32BIT_KERNEL
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
-	select TOSHIBA_BOARDS
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 
 config TOSHIBA_RBTX4927
@@ -791,7 +632,6 @@
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_KGDB
-	select TOSHIBA_BOARDS
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
 	  This Toshiba board is based on the TX4927 processor. Say Y here to
@@ -811,7 +651,6 @@
 	select SYS_SUPPORTS_LITTLE_ENDIAN
 	select SYS_SUPPORTS_BIG_ENDIAN
 	select SYS_SUPPORTS_KGDB
-	select TOSHIBA_BOARDS
 	select GENERIC_HARDIRQS_NO__DO_IRQ
 	help
 	  This Toshiba board is based on the TX4938 processor. Say Y here to
@@ -819,11 +658,11 @@
 
 endchoice
 
+source "arch/mips/au1000/Kconfig"
 source "arch/mips/ddb5xxx/Kconfig"
 source "arch/mips/gt64120/ev64120/Kconfig"
 source "arch/mips/jazz/Kconfig"
 source "arch/mips/lasat/Kconfig"
-source "arch/mips/momentum/Kconfig"
 source "arch/mips/pmc-sierra/Kconfig"
 source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
@@ -923,11 +762,6 @@
 config I8259
 	bool
 
-config LIMITED_DMA
-	bool
-	select HIGHMEM
-	select SYS_SUPPORTS_HIGHMEM
-
 config MIPS_BONITO64
 	bool
 
@@ -1013,33 +847,6 @@
 config PCI_MARVELL
 	bool
 
-config SOC_AU1000
-	bool
-	select SOC_AU1X00
-
-config SOC_AU1100
-	bool
-	select SOC_AU1X00
-
-config SOC_AU1500
-	bool
-	select SOC_AU1X00
-
-config SOC_AU1550
-	bool
-	select SOC_AU1X00
-
-config SOC_AU1200
-	bool
-	select SOC_AU1X00
-
-config SOC_AU1X00
-	bool
-	select SYS_HAS_CPU_MIPS32_R1
-	select SYS_SUPPORTS_32BIT_KERNEL
-	select SYS_SUPPORTS_APM_EMULATION
-	select SYS_SUPPORTS_KGDB
-
 config SERIAL_RM9000
 	bool
 
@@ -1081,9 +888,9 @@
 choice
 	prompt "Galileo Chip Clock"
 	#default SYSCLK_83 if MIPS_EV64120
-	depends on MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+	depends on MIPS_EV64120 || MOMENCO_OCELOT
 	default SYSCLK_83 if MIPS_EV64120
-	default SYSCLK_100 if MOMENCO_OCELOT || MOMENCO_OCELOT_G
+	default SYSCLK_100 if MOMENCO_OCELOT
 
 config SYSCLK_75
 	bool "75" if MIPS_EV64120
@@ -1092,7 +899,7 @@
 	bool "83.3" if MIPS_EV64120
 
 config SYSCLK_100
-	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT || MOMENCO_OCELOT_G
+	bool "100" if MIPS_EV64120 || MOMENCO_OCELOT
 
 endchoice
 
@@ -1131,9 +938,6 @@
 config BOOT_ELF64
 	bool
 
-config TOSHIBA_BOARDS
-	bool
-
 menu "CPU selection"
 
 choice
@@ -1557,6 +1361,7 @@
 	bool "Use 1 TC on each available VPE for SMP"
 	depends on SYS_SUPPORTS_MULTITHREADING
 	select CPU_MIPSR2_IRQ_VI
+	select CPU_MIPSR2_IRQ_EI
 	select CPU_MIPSR2_SRS
 	select MIPS_MT
 	select NR_CPUS_DEFAULT_2
@@ -1572,6 +1377,7 @@
 	#depends on CPU_MIPS64_R2		# once there is hardware ...
 	depends on SYS_SUPPORTS_MULTITHREADING
 	select CPU_MIPSR2_IRQ_VI
+	select CPU_MIPSR2_IRQ_EI
 	select CPU_MIPSR2_SRS
 	select MIPS_MT
 	select NR_CPUS_DEFAULT_8
@@ -1584,6 +1390,8 @@
 config MIPS_VPE_LOADER
 	bool "VPE loader support."
 	depends on SYS_SUPPORTS_MULTITHREADING
+	select CPU_MIPSR2_IRQ_VI
+	select CPU_MIPSR2_IRQ_EI
 	select MIPS_MT
 	help
 	  Includes a loader for loading an elf relocatable object
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 4892db8..f450066 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -343,15 +343,6 @@
 load-$(CONFIG_MOMENCO_OCELOT)	+= 0xffffffff80100000
 
 #
-# Momentum Ocelot-G board
-#
-# The Ocelot-G setup.o must be linked early - it does the ioremap() for the
-# mips_io_port_base.
-#
-core-$(CONFIG_MOMENCO_OCELOT_G)	+= arch/mips/momentum/ocelot_g/
-load-$(CONFIG_MOMENCO_OCELOT_G)	+= 0xffffffff80100000
-
-#
 # Momentum Ocelot-C and -CS boards
 #
 # The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the
@@ -388,17 +379,6 @@
 load-$(CONFIG_BASLER_EXCITE)	+= 0x80100000
 
 #
-# Momentum Jaguar ATX
-#
-core-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= arch/mips/momentum/jaguar_atx/
-cflags-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= -Iinclude/asm-mips/mach-ja
-#ifdef CONFIG_JAGUAR_DMALOW
-#load-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= 0xffffffff88000000
-#else
-load-$(CONFIG_MOMENCO_JAGUAR_ATX)	+= 0xffffffff80100000
-#endif
-
-#
 # NEC DDB
 #
 core-$(CONFIG_DDB5XXX_COMMON)	+= arch/mips/ddb5xxx/common/
@@ -729,3 +709,25 @@
 CLEAN_FILES += vmlinux.32 \
 	       vmlinux.64 \
 	       vmlinux.ecoff
+
+quiet_cmd_syscalls_n32 = CALL-N32 $<
+      cmd_syscalls_n32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=n32
+
+quiet_cmd_syscalls_o32 = CALL-O32 $<
+      cmd_syscalls_o32 = $(CONFIG_SHELL) $< $(CC) $(c_flags) -mabi=32
+
+PHONY += missing-syscalls-n32 missing-syscalls-o32
+
+missing-syscalls-n32: scripts/checksyscalls.sh FORCE
+	$(call cmd,syscalls_n32)
+
+missing-syscalls-o32: scripts/checksyscalls.sh FORCE
+	$(call cmd,syscalls_o32)
+
+archprepare:
+ifdef CONFIG_MIPS32_N32
+	$(Q)$(MAKE) $(build)=arch/mips missing-syscalls-n32
+endif
+ifdef CONFIG_MIPS32_O32
+	$(Q)$(MAKE) $(build)=arch/mips missing-syscalls-o32
+endif
diff --git a/arch/mips/au1000/Kconfig b/arch/mips/au1000/Kconfig
new file mode 100644
index 0000000..abea880
--- /dev/null
+++ b/arch/mips/au1000/Kconfig
@@ -0,0 +1,142 @@
+choice
+	prompt "Machine type"
+	depends on MACH_ALCHEMY
+	default MIPS_DB1000
+
+config MIPS_MTX1
+	bool "4G Systems MTX-1 board"
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
+	select SOC_AU1500
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_BOSPORUS
+	bool "Alchemy Bosporus board"
+	select SOC_AU1500
+	select DMA_NONCOHERENT
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1000
+	bool "Alchemy DB1000 board"
+	select SOC_AU1000
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1100
+	bool "Alchemy DB1100 board"
+	select SOC_AU1100
+	select DMA_NONCOHERENT
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1200
+	bool "Alchemy DB1200 board"
+	select SOC_AU1200
+	select DMA_COHERENT
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1500
+	bool "Alchemy DB1500 board"
+	select SOC_AU1500
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
+	select SYS_SUPPORTS_BIG_ENDIAN
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_DB1550
+	bool "Alchemy DB1550 board"
+	select SOC_AU1550
+	select HW_HAS_PCI
+	select DMA_NONCOHERENT
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_MIRAGE
+	bool "Alchemy Mirage board"
+	select DMA_NONCOHERENT
+	select SOC_AU1500
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1000
+	bool "Alchemy PB1000 board"
+	select SOC_AU1000
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
+	select SWAP_IO_SPACE
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1100
+	bool "Alchemy PB1100 board"
+	select SOC_AU1100
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
+	select SWAP_IO_SPACE
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1200
+	bool "Alchemy PB1200 board"
+	select SOC_AU1200
+	select DMA_NONCOHERENT
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1500
+	bool "Alchemy PB1500 board"
+	select SOC_AU1500
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select RESOURCES_64BIT if PCI
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_PB1550
+	bool "Alchemy PB1550 board"
+	select SOC_AU1550
+	select DMA_NONCOHERENT
+	select HW_HAS_PCI
+	select MIPS_DISABLE_OBSOLETE_IDE
+	select RESOURCES_64BIT if PCI
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+config MIPS_XXS1500
+	bool "MyCable XXS1500 board"
+	select DMA_NONCOHERENT
+	select SOC_AU1500
+	select SYS_SUPPORTS_LITTLE_ENDIAN
+
+endchoice
+
+config SOC_AU1000
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1100
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1500
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1550
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1200
+	bool
+	select SOC_AU1X00
+
+config SOC_AU1X00
+	bool
+	select SYS_HAS_CPU_MIPS32_R1
+	select SYS_SUPPORTS_32BIT_KERNEL
+	select SYS_SUPPORTS_APM_EMULATION
+	select SYS_SUPPORTS_KGDB
diff --git a/arch/mips/basler/excite/excite_device.c b/arch/mips/basler/excite/excite_device.c
index cc1ce77..e00bc2d 100644
--- a/arch/mips/basler/excite/excite_device.c
+++ b/arch/mips/basler/excite/excite_device.c
@@ -68,7 +68,7 @@
 
 
 static struct resource
-	excite_ctr_resource __attribute__((unused)) = {
+	excite_ctr_resource __maybe_unused = {
 		.name		= "GPI counters",
 		.start		= 0,
 		.end		= 5,
@@ -77,7 +77,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_gpislice_resource __attribute__((unused)) = {
+	excite_gpislice_resource __maybe_unused = {
 		.name		= "GPI slices",
 		.start		= 0,
 		.end		= 1,
@@ -86,7 +86,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_mdio_channel_resource __attribute__((unused)) = {
+	excite_mdio_channel_resource __maybe_unused = {
 		.name		= "MDIO channels",
 		.start		= 0,
 		.end		= 1,
@@ -95,7 +95,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_fifomem_resource __attribute__((unused)) = {
+	excite_fifomem_resource __maybe_unused = {
 		.name		= "FIFO memory",
 		.start		= 0,
 		.end		= 767,
@@ -104,7 +104,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_scram_resource __attribute__((unused)) = {
+	excite_scram_resource __maybe_unused = {
 		.name		= "Scratch RAM",
 		.start		= EXCITE_PHYS_SCRAM,
 		.end		= EXCITE_PHYS_SCRAM + EXCITE_SIZE_SCRAM - 1,
@@ -113,7 +113,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_fpga_resource __attribute__((unused)) = {
+	excite_fpga_resource __maybe_unused = {
 		.name		= "System FPGA",
 		.start		= EXCITE_PHYS_FPGA,
 		.end		= EXCITE_PHYS_FPGA + EXCITE_SIZE_FPGA - 1,
@@ -122,7 +122,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_nand_resource __attribute__((unused)) = {
+	excite_nand_resource __maybe_unused = {
 		.name		= "NAND flash control",
 		.start		= EXCITE_PHYS_NAND,
 		.end		= EXCITE_PHYS_NAND + EXCITE_SIZE_NAND - 1,
@@ -131,7 +131,7 @@
 		.sibling	= NULL,
 		.child		= NULL
 	},
-	excite_titan_resource __attribute__((unused)) = {
+	excite_titan_resource __maybe_unused = {
 		.name		= "TITAN registers",
 		.start		= EXCITE_PHYS_TITAN,
 		.end		= EXCITE_PHYS_TITAN + EXCITE_SIZE_TITAN - 1,
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index 9565b21..c292f80 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the Cobalt micro systems family specific parts of the kernel
 #
 
-obj-y	 := irq.o reset.o setup.o buttons.o
+obj-y := buttons.o irq.o reset.o rtc.o serial.o setup.o
 
 obj-$(CONFIG_PCI)		+= pci.o
 obj-$(CONFIG_EARLY_PRINTK)	+= console.o
diff --git a/arch/mips/cobalt/rtc.c b/arch/mips/cobalt/rtc.c
new file mode 100644
index 0000000..284daef
--- /dev/null
+++ b/arch/mips/cobalt/rtc.c
@@ -0,0 +1,63 @@
+/*
+ *  Registration of Cobalt RTC platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+static struct resource cobalt_rtc_resource[] __initdata = {
+	{
+		.start	= 0x70,
+		.end	= 0x77,
+		.flags	= IORESOURCE_IO,
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static __init int cobalt_rtc_add(void)
+{
+	struct platform_device *pdev;
+	int retval;
+
+	pdev = platform_device_alloc("rtc_cmos", -1);
+	if (!pdev)
+		return -ENOMEM;
+
+	retval = platform_device_add_resources(pdev, cobalt_rtc_resource,
+	                                       ARRAY_SIZE(cobalt_rtc_resource));
+	if (retval)
+		goto err_free_device;
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	platform_device_put(pdev);
+
+	return retval;
+}
+device_initcall(cobalt_rtc_add);
diff --git a/arch/mips/cobalt/serial.c b/arch/mips/cobalt/serial.c
new file mode 100644
index 0000000..c271165
--- /dev/null
+++ b/arch/mips/cobalt/serial.c
@@ -0,0 +1,85 @@
+/*
+ *  Registration of Cobalt UART platform device.
+ *
+ *  Copyright (C) 2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+
+#include <cobalt.h>
+
+static struct resource cobalt_uart_resource[] __initdata = {
+	{
+		.start	= 0x1c800000,
+		.end	= 0x1c800007,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= COBALT_SERIAL_IRQ,
+		.end	= COBALT_SERIAL_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct plat_serial8250_port cobalt_serial8250_port[] = {
+	{
+		.irq		= COBALT_SERIAL_IRQ,
+		.uartclk	= 18432000,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_IOREMAP | UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.mapbase	= 0x1c800000,
+	},
+	{},
+};
+
+static __init int cobalt_uart_add(void)
+{
+	struct platform_device *pdev;
+	int retval;
+
+	/*
+	 * Cobalt Qube1 and RAQ1 have no UART.
+	 */
+	if (cobalt_board_id <= COBALT_BRD_ID_RAQ1)
+		return 0;
+
+	pdev = platform_device_alloc("serial8250", -1);
+	if (!pdev)
+		return -ENOMEM;
+
+	pdev->id = PLAT8250_DEV_PLATFORM;
+	pdev->dev.platform_data = cobalt_serial8250_port;
+
+	retval = platform_device_add_resources(pdev, cobalt_uart_resource, ARRAY_SIZE(cobalt_uart_resource));
+	if (retval)
+		goto err_free_device;
+
+	retval = platform_device_add(pdev);
+	if (retval)
+		goto err_free_device;
+
+	return 0;
+
+err_free_device:
+	platform_device_put(pdev);
+
+	return retval;
+}
+device_initcall(cobalt_uart_add);
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index d0dd817..7abe45e 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -10,11 +10,8 @@
  *
  */
 #include <linux/interrupt.h>
-#include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/pm.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
 
 #include <asm/bootinfo.h>
 #include <asm/time.h>
@@ -27,9 +24,6 @@
 extern void cobalt_machine_restart(char *command);
 extern void cobalt_machine_halt(void);
 extern void cobalt_machine_power_off(void);
-extern void cobalt_early_console(void);
-
-int cobalt_board_id;
 
 const char *get_system_type(void)
 {
@@ -95,8 +89,6 @@
 
 void __init plat_mem_setup(void)
 {
-	static struct uart_port uart;
-	unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
 	int i;
 
 	_machine_restart = cobalt_machine_restart;
@@ -111,29 +103,6 @@
 	/* These resources have been reserved by VIA SuperI/O chip. */
 	for (i = 0; i < ARRAY_SIZE(cobalt_reserved_resources); i++)
 		request_resource(&ioport_resource, cobalt_reserved_resources + i);
-
-        /* Read the cobalt id register out of the PCI config space */
-        PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
-        cobalt_board_id = GT_READ(GT_PCI0_CFGDATA_OFS);
-        cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
-        cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
-
-	printk("Cobalt board ID: %d\n", cobalt_board_id);
-
-	if (cobalt_board_id > COBALT_BRD_ID_RAQ1) {
-#ifdef CONFIG_SERIAL_8250
-		uart.line	= 0;
-		uart.type	= PORT_UNKNOWN;
-		uart.uartclk	= 18432000;
-		uart.irq	= COBALT_SERIAL_IRQ;
-		uart.flags	= UPF_IOREMAP | UPF_BOOT_AUTOCONF |
-				  UPF_SKIP_TEST;
-		uart.iotype	= UPIO_MEM;
-		uart.mapbase	= 0x1c800000;
-
-		early_serial_setup(&uart);
-#endif
-	}
 }
 
 /*
diff --git a/arch/mips/configs/cobalt_defconfig b/arch/mips/configs/cobalt_defconfig
index ba593b5..631b213 100644
--- a/arch/mips/configs/cobalt_defconfig
+++ b/arch/mips/configs/cobalt_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:24 2007
+# Linux kernel version: 2.6.21-rc7
+# Wed Apr 18 14:25:45 2007
 #
 CONFIG_MIPS=y
 
@@ -62,7 +62,6 @@
 # CONFIG_TOSHIBA_JMR3927 is not set
 # CONFIG_TOSHIBA_RBTX4927 is not set
 # CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_EARLY_PRINTK=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -74,12 +73,14 @@
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
 CONFIG_I8259=y
 # CONFIG_CPU_BIG_ENDIAN is not set
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_IRQ_CPU=y
-CONFIG_MIPS_GT64111=y
+CONFIG_PCI_GT64XXX_PCI0=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
@@ -179,6 +180,7 @@
 # CONFIG_IKCONFIG is not set
 CONFIG_SYSFS_DEPRECATED=y
 CONFIG_RELAY=y
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -477,7 +479,6 @@
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
 CONFIG_CDROM_PKTCDVD=y
 CONFIG_CDROM_PKTCDVD_BUFFERS=8
 # CONFIG_CDROM_PKTCDVD_WCACHE is not set
@@ -518,7 +519,7 @@
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -546,7 +547,6 @@
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-# CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -779,7 +779,8 @@
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_HW_RANDOM is not set
-CONFIG_RTC=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
 CONFIG_COBALT_LCD=y
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
@@ -815,6 +816,11 @@
 # CONFIG_HWMON_VID is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -827,7 +833,7 @@
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 
 #
@@ -835,7 +841,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -894,7 +899,29 @@
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+
+#
+# RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_TEST is not set
+# CONFIG_RTC_DRV_V3020 is not set
 
 #
 # DMA Engine support
diff --git a/arch/mips/configs/db1000_defconfig b/arch/mips/configs/db1000_defconfig
index 0db6a8b..10f6af4 100644
--- a/arch/mips/configs/db1000_defconfig
+++ b/arch/mips/configs/db1000_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1100_defconfig b/arch/mips/configs/db1100_defconfig
index 162add9..4b08629 100644
--- a/arch/mips/configs/db1100_defconfig
+++ b/arch/mips/configs/db1100_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1200_defconfig b/arch/mips/configs/db1200_defconfig
index 82801ec..820659e 100644
--- a/arch/mips/configs/db1200_defconfig
+++ b/arch/mips/configs/db1200_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1500_defconfig b/arch/mips/configs/db1500_defconfig
index 545f230..4050b9b 100644
--- a/arch/mips/configs/db1500_defconfig
+++ b/arch/mips/configs/db1500_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/db1550_defconfig b/arch/mips/configs/db1550_defconfig
index 5bd3b43..7b35190 100644
--- a/arch/mips/configs/db1550_defconfig
+++ b/arch/mips/configs/db1550_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/jaguar-atx_defconfig b/arch/mips/configs/jaguar-atx_defconfig
deleted file mode 100644
index 083104d..0000000
--- a/arch/mips/configs/jaguar-atx_defconfig
+++ /dev/null
@@ -1,897 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:33 2007
-#
-CONFIG_MIPS=y
-
-#
-# Machine selection
-#
-CONFIG_ZONE_DMA=y
-# CONFIG_MIPS_MTX1 is not set
-# CONFIG_MIPS_BOSPORUS is not set
-# CONFIG_MIPS_PB1000 is not set
-# CONFIG_MIPS_PB1100 is not set
-# CONFIG_MIPS_PB1500 is not set
-# CONFIG_MIPS_PB1550 is not set
-# CONFIG_MIPS_PB1200 is not set
-# CONFIG_MIPS_DB1000 is not set
-# CONFIG_MIPS_DB1100 is not set
-# CONFIG_MIPS_DB1500 is not set
-# CONFIG_MIPS_DB1550 is not set
-# CONFIG_MIPS_DB1200 is not set
-# CONFIG_MIPS_MIRAGE is not set
-# CONFIG_BASLER_EXCITE is not set
-# CONFIG_MIPS_COBALT is not set
-# CONFIG_MACH_DECSTATION is not set
-# CONFIG_MIPS_EV64120 is not set
-# CONFIG_MACH_JAZZ is not set
-# CONFIG_LASAT is not set
-# CONFIG_MIPS_ATLAS is not set
-# CONFIG_MIPS_MALTA is not set
-# CONFIG_MIPS_SEAD is not set
-# CONFIG_WR_PPMC is not set
-# CONFIG_MIPS_SIM is not set
-CONFIG_MOMENCO_JAGUAR_ATX=y
-# CONFIG_MOMENCO_OCELOT is not set
-# CONFIG_MOMENCO_OCELOT_3 is not set
-# CONFIG_MOMENCO_OCELOT_C is not set
-# CONFIG_MOMENCO_OCELOT_G is not set
-# CONFIG_MIPS_XXS1500 is not set
-# CONFIG_PNX8550_JBS is not set
-# CONFIG_PNX8550_STB810 is not set
-# CONFIG_DDB5477 is not set
-# CONFIG_MACH_VR41XX is not set
-# CONFIG_PMC_YOSEMITE is not set
-# CONFIG_QEMU is not set
-# CONFIG_MARKEINS is not set
-# CONFIG_SGI_IP22 is not set
-# CONFIG_SGI_IP27 is not set
-# CONFIG_SGI_IP32 is not set
-# CONFIG_SIBYTE_BIGSUR is not set
-# CONFIG_SIBYTE_SWARM is not set
-# CONFIG_SIBYTE_SENTOSA is not set
-# CONFIG_SIBYTE_RHONE is not set
-# CONFIG_SIBYTE_CARMEL is not set
-# CONFIG_SIBYTE_PTSWARM is not set
-# CONFIG_SIBYTE_LITTLESUR is not set
-# CONFIG_SIBYTE_CRHINE is not set
-# CONFIG_SIBYTE_CRHONE is not set
-# CONFIG_SNI_RM is not set
-# CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
-# CONFIG_TOSHIBA_RBTX4938 is not set
-CONFIG_JAGUAR_DMALOW=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_FIND_NEXT_BIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_TIME=y
-CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
-CONFIG_DMA_NONCOHERENT=y
-CONFIG_DMA_NEED_PCI_MAP_STATE=y
-CONFIG_LIMITED_DMA=y
-CONFIG_CPU_BIG_ENDIAN=y
-# CONFIG_CPU_LITTLE_ENDIAN is not set
-CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_IRQ_MV64340=y
-CONFIG_PCI_MARVELL=y
-CONFIG_SWAP_IO_SPACE=y
-CONFIG_BOOT_ELF32=y
-CONFIG_MIPS_L1_CACHE_SHIFT=5
-
-#
-# CPU selection
-#
-# CONFIG_CPU_MIPS32_R1 is not set
-# CONFIG_CPU_MIPS32_R2 is not set
-# CONFIG_CPU_MIPS64_R1 is not set
-# CONFIG_CPU_MIPS64_R2 is not set
-# CONFIG_CPU_R3000 is not set
-# CONFIG_CPU_TX39XX is not set
-# CONFIG_CPU_VR41XX is not set
-# CONFIG_CPU_R4300 is not set
-# CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
-# CONFIG_CPU_R5000 is not set
-# CONFIG_CPU_R5432 is not set
-# CONFIG_CPU_R6000 is not set
-# CONFIG_CPU_NEVADA is not set
-# CONFIG_CPU_R8000 is not set
-# CONFIG_CPU_R10000 is not set
-# CONFIG_CPU_RM7000 is not set
-CONFIG_CPU_RM9000=y
-# CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM9000=y
-CONFIG_WEAK_ORDERING=y
-CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
-CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
-CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
-
-#
-# Kernel type
-#
-CONFIG_32BIT=y
-# CONFIG_64BIT is not set
-CONFIG_PAGE_SIZE_4KB=y
-# CONFIG_PAGE_SIZE_8KB is not set
-# CONFIG_PAGE_SIZE_16KB is not set
-# CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
-CONFIG_CPU_HAS_PREFETCH=y
-CONFIG_MIPS_MT_DISABLED=y
-# CONFIG_MIPS_MT_SMP is not set
-# CONFIG_MIPS_MT_SMTC is not set
-# CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
-CONFIG_CPU_HAS_LLSC=y
-CONFIG_CPU_HAS_SYNC=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_HIGHMEM=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
-CONFIG_SYS_SUPPORTS_HIGHMEM=y
-CONFIG_ARCH_FLATMEM_ENABLE=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-# CONFIG_HZ_48 is not set
-# CONFIG_HZ_100 is not set
-# CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
-# CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
-# CONFIG_HZ_1024 is not set
-CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SHMEM=y
-CONFIG_SLAB=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_KMOD=y
-
-#
-# Block layer
-#
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-CONFIG_DEFAULT_AS=y
-# CONFIG_DEFAULT_DEADLINE is not set
-# CONFIG_DEFAULT_CFQ is not set
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="anticipatory"
-
-#
-# Bus options (PCI, PCMCIA, EISA, ISA, TC)
-#
-CONFIG_HW_HAS_PCI=y
-CONFIG_PCI=y
-CONFIG_MMU=y
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_TRAD_SIGNALS=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
-
-#
-# Networking
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=m
-CONFIG_INET_XFRM_MODE_TRANSPORT=m
-CONFIG_INET_XFRM_MODE_TUNNEL=m
-CONFIG_INET_XFRM_MODE_BEET=m
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_IPV6=m
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_INET6_AH=m
-CONFIG_INET6_ESP=m
-CONFIG_INET6_IPCOMP=m
-CONFIG_INET6_XFRM_TUNNEL=m
-CONFIG_INET6_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_TRANSPORT=m
-CONFIG_INET6_XFRM_MODE_TUNNEL=m
-CONFIG_INET6_XFRM_MODE_BEET=m
-CONFIG_IPV6_SIT=m
-CONFIG_IPV6_TUNNEL=m
-CONFIG_NETWORK_SECMARK=y
-# CONFIG_NETFILTER is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_IEEE80211=m
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=m
-CONFIG_IEEE80211_CRYPT_CCMP=m
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-# CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
-CONFIG_CONNECTOR=m
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-CONFIG_ATA_OVER_ETH=m
-
-#
-# Misc devices
-#
-CONFIG_SGI_IOC4=m
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_RAID_ATTRS=m
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_NETLINK is not set
-
-#
-# Serial ATA (prod) and Parallel ATA (experimental) drivers
-#
-# CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-# CONFIG_FUSION is not set
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Network device support
-#
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# PHY device support
-#
-CONFIG_PHYLIB=m
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=m
-CONFIG_DAVICOM_PHY=m
-CONFIG_QSEMI_PHY=m
-CONFIG_LXT_PHY=m
-CONFIG_CICADA_PHY=m
-CONFIG_VITESSE_PHY=m
-CONFIG_SMSC_PHY=m
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_CASSINI is not set
-# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_DM9000 is not set
-
-#
-# Tulip family network device support
-#
-# CONFIG_NET_TULIP is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=y
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
-# CONFIG_SKGE is not set
-# CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_TIGON3 is not set
-# CONFIG_BNX2 is not set
-CONFIG_MV643XX_ETH=y
-CONFIG_QLA3XXX=m
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=m
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-# CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=m
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_JSM is not set
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# SPI support
-#
-# CONFIG_SPI is not set
-# CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Hardware Monitoring support
-#
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-# CONFIG_USB is not set
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# LED devices
-#
-# CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
-# CONFIG_INFINIBAND is not set
-
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
-#
-# Real Time Clock
-#
-
-#
-# DMA Engine support
-#
-# CONFIG_DMA_ENGINE is not set
-
-#
-# DMA Clients
-#
-
-#
-# DMA Devices
-#
-
-#
-# Auxiliary Display support
-#
-
-#
-# Virtualization
-#
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=m
-CONFIG_GENERIC_ACL=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Kernel hacking
-#
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_MUST_CHECK=y
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_CROSSCOMPILE=y
-CONFIG_CMDLINE=""
-CONFIG_SYS_SUPPORTS_KGDB=y
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=m
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_TGR192=m
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_CBC=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_DES=m
-CONFIG_CRYPTO_FCRYPT=m
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_TWOFISH_COMMON=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-CONFIG_CRYPTO_ARC4=m
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_CAMELLIA=m
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=m
-# CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=m
-CONFIG_CRC32=m
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
diff --git a/arch/mips/configs/jmr3927_defconfig b/arch/mips/configs/jmr3927_defconfig
index 068e48e..1b364cf 100644
--- a/arch/mips/configs/jmr3927_defconfig
+++ b/arch/mips/configs/jmr3927_defconfig
@@ -80,7 +80,6 @@
 CONFIG_MIPS_TX3927=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
-CONFIG_TOSHIBA_BOARDS=y
 
 #
 # CPU selection
diff --git a/arch/mips/configs/pb1100_defconfig b/arch/mips/configs/pb1100_defconfig
index 69678d9..37d696c 100644
--- a/arch/mips/configs/pb1100_defconfig
+++ b/arch/mips/configs/pb1100_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/pb1500_defconfig b/arch/mips/configs/pb1500_defconfig
index 0706727..b11f0e8 100644
--- a/arch/mips/configs/pb1500_defconfig
+++ b/arch/mips/configs/pb1500_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/pb1550_defconfig b/arch/mips/configs/pb1550_defconfig
index 354e49b..2927f38 100644
--- a/arch/mips/configs/pb1550_defconfig
+++ b/arch/mips/configs/pb1550_defconfig
@@ -9,6 +9,7 @@
 # Machine selection
 #
 CONFIG_ZONE_DMA=y
+CONFIG_MACH_ALCHEMY=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
diff --git a/arch/mips/configs/ocelot_g_defconfig b/arch/mips/configs/rbhma4200_defconfig
similarity index 73%
rename from arch/mips/configs/ocelot_g_defconfig
rename to arch/mips/configs/rbhma4200_defconfig
index 7078e6b..35d6426 100644
--- a/arch/mips/configs/ocelot_g_defconfig
+++ b/arch/mips/configs/rbhma4200_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:36 2007
+# Linux kernel version: 2.6.21
+# Wed May  9 23:44:19 2007
 #
 CONFIG_MIPS=y
 
 #
 # Machine selection
 #
-CONFIG_ZONE_DMA=y
 # CONFIG_MIPS_MTX1 is not set
 # CONFIG_MIPS_BOSPORUS is not set
 # CONFIG_MIPS_PB1000 is not set
@@ -33,11 +32,9 @@
 # CONFIG_MIPS_SEAD is not set
 # CONFIG_WR_PPMC is not set
 # CONFIG_MIPS_SIM is not set
-# CONFIG_MOMENCO_JAGUAR_ATX is not set
 # CONFIG_MOMENCO_OCELOT is not set
 # CONFIG_MOMENCO_OCELOT_3 is not set
 # CONFIG_MOMENCO_OCELOT_C is not set
-CONFIG_MOMENCO_OCELOT_G=y
 # CONFIG_MIPS_XXS1500 is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
@@ -60,8 +57,9 @@
 # CONFIG_SIBYTE_CRHONE is not set
 # CONFIG_SNI_RM is not set
 # CONFIG_TOSHIBA_JMR3927 is not set
-# CONFIG_TOSHIBA_RBTX4927 is not set
+CONFIG_TOSHIBA_RBTX4927=y
 # CONFIG_TOSHIBA_RBTX4938 is not set
+# CONFIG_TOSHIBA_FPCIB0 is not set
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
@@ -70,19 +68,15 @@
 CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_TIME=y
 CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
-# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_I8259=y
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
-CONFIG_IRQ_CPU=y
-CONFIG_IRQ_CPU_RM7K=y
-CONFIG_PCI_MARVELL=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
 CONFIG_SWAP_IO_SPACE=y
-# CONFIG_SYSCLK_75 is not set
-# CONFIG_SYSCLK_83 is not set
-CONFIG_SYSCLK_100=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 
 #
@@ -97,18 +91,19 @@
 # CONFIG_CPU_VR41XX is not set
 # CONFIG_CPU_R4300 is not set
 # CONFIG_CPU_R4X00 is not set
-# CONFIG_CPU_TX49XX is not set
+CONFIG_CPU_TX49XX=y
 # CONFIG_CPU_R5000 is not set
 # CONFIG_CPU_R5432 is not set
 # CONFIG_CPU_R6000 is not set
 # CONFIG_CPU_NEVADA is not set
 # CONFIG_CPU_R8000 is not set
 # CONFIG_CPU_R10000 is not set
-CONFIG_CPU_RM7000=y
+# CONFIG_CPU_RM7000 is not set
 # CONFIG_CPU_RM9000 is not set
 # CONFIG_CPU_SB1 is not set
-CONFIG_SYS_HAS_CPU_RM7000=y
+CONFIG_SYS_HAS_CPU_TX49XX=y
 CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
 CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
 
@@ -121,19 +116,15 @@
 # CONFIG_PAGE_SIZE_8KB is not set
 # CONFIG_PAGE_SIZE_16KB is not set
 # CONFIG_PAGE_SIZE_64KB is not set
-CONFIG_BOARD_SCACHE=y
-CONFIG_RM7000_CPU_SCACHE=y
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_MIPS_MT_DISABLED=y
 # CONFIG_MIPS_MT_SMP is not set
 # CONFIG_MIPS_MT_SMTC is not set
 # CONFIG_MIPS_VPE_LOADER is not set
-# CONFIG_64BIT_PHYS_ADDR is not set
 CONFIG_CPU_HAS_LLSC=y
 CONFIG_CPU_HAS_SYNC=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_ARCH_FLATMEM_ENABLE=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
@@ -143,17 +134,17 @@
 CONFIG_FLAT_NODE_MEM_MAP=y
 # CONFIG_SPARSEMEM_STATIC is not set
 CONFIG_SPLIT_PTLOCK_CPUS=4
-CONFIG_RESOURCES_64BIT=y
-CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
 # CONFIG_HZ_48 is not set
 # CONFIG_HZ_100 is not set
 # CONFIG_HZ_128 is not set
-# CONFIG_HZ_250 is not set
+CONFIG_HZ_250=y
 # CONFIG_HZ_256 is not set
-CONFIG_HZ_1000=y
+# CONFIG_HZ_1000 is not set
 # CONFIG_HZ_1024 is not set
 CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
-CONFIG_HZ=1000
+CONFIG_HZ=250
 CONFIG_PREEMPT_NONE=y
 # CONFIG_PREEMPT_VOLUNTARY is not set
 # CONFIG_PREEMPT is not set
@@ -183,34 +174,42 @@
 # CONFIG_TASKSTATS is not set
 # CONFIG_UTS_NS is not set
 # CONFIG_AUDIT is not set
-# CONFIG_IKCONFIG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED=y
-CONFIG_RELAY=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
 CONFIG_SYSCTL_SYSCALL=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
+# CONFIG_HOTPLUG is not set
 CONFIG_PRINTK=y
 CONFIG_BUG=y
 CONFIG_ELF_CORE=y
 CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_RT_MUTEXES=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
 
 #
 # Block layer
@@ -218,7 +217,7 @@
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_LSF=y
+# CONFIG_LSF is not set
 
 #
 # IO Schedulers
@@ -238,17 +237,12 @@
 #
 CONFIG_HW_HAS_PCI=y
 CONFIG_PCI=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_MMU=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
-# CONFIG_PCCARD is not set
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -260,10 +254,7 @@
 #
 # Power management options
 #
-CONFIG_PM=y
-# CONFIG_PM_LEGACY is not set
-# CONFIG_PM_DEBUG is not set
-# CONFIG_PM_SYSFS_DEPRECATED is not set
+# CONFIG_PM is not set
 
 #
 # Networking
@@ -273,25 +264,21 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
-# CONFIG_PACKET is not set
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
+# CONFIG_NET_KEY is not set
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_DHCP is not set
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
@@ -299,19 +286,19 @@
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
 # CONFIG_INET_TUNNEL is not set
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
 CONFIG_INET_DIAG=y
 CONFIG_INET_TCP_DIAG=y
 # CONFIG_TCP_CONG_ADVANCED is not set
 CONFIG_TCP_CONG_CUBIC=y
 CONFIG_DEFAULT_TCP_CONG="cubic"
-CONFIG_TCP_MD5SIG=y
+# CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 # CONFIG_INET6_XFRM_TUNNEL is not set
 # CONFIG_INET6_TUNNEL is not set
-CONFIG_NETWORK_SECMARK=y
+# CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
 
 #
@@ -352,13 +339,16 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
-CONFIG_IEEE80211=y
-# CONFIG_IEEE80211_DEBUG is not set
-CONFIG_IEEE80211_CRYPT_WEP=y
-CONFIG_IEEE80211_CRYPT_CCMP=y
-CONFIG_IEEE80211_SOFTMAC=y
-# CONFIG_IEEE80211_SOFTMAC_DEBUG is not set
-CONFIG_WIRELESS_EXT=y
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
 
 #
 # Device Drivers
@@ -369,18 +359,12 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
-CONFIG_CONNECTOR=y
-CONFIG_PROC_EVENTS=y
-
-#
-# Memory Technology Devices (MTD)
-#
+# CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
 
 #
@@ -401,21 +385,24 @@
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CDROM_PKTCDVD=y
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-CONFIG_ATA_OVER_ETH=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # Misc devices
 #
-CONFIG_SGI_IOC4=y
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
+# CONFIG_BLINK is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -425,7 +412,7 @@
 #
 # SCSI device support
 #
-CONFIG_RAID_ATTRS=y
+# CONFIG_RAID_ATTRS is not set
 # CONFIG_SCSI is not set
 # CONFIG_SCSI_NETLINK is not set
 
@@ -471,27 +458,13 @@
 #
 # PHY device support
 #
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-CONFIG_MARVELL_PHY=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_QSEMI_PHY=y
-CONFIG_LXT_PHY=y
-CONFIG_CICADA_PHY=y
-CONFIG_VITESSE_PHY=y
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_FIXED_PHY is not set
+# CONFIG_PHYLIB is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_GALILEO_64240_ETH=y
+# CONFIG_MII is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
@@ -503,6 +476,7 @@
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
+CONFIG_NE2000=y
 # CONFIG_NET_PCI is not set
 
 #
@@ -521,18 +495,18 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
-CONFIG_QLA3XXX=y
+# CONFIG_QLA3XXX is not set
 # CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
-CONFIG_CHELSIO_T3=y
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
-CONFIG_NETXEN_NIC=y
+# CONFIG_NETXEN_NIC is not set
 
 #
 # Token Ring devices
@@ -540,9 +514,10 @@
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
 # Wan interfaces
@@ -570,29 +545,7 @@
 #
 # Input device support
 #
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
+# CONFIG_INPUT is not set
 
 #
 # Hardware I/O ports
@@ -601,34 +554,31 @@
 # CONFIG_SERIO_I8042 is not set
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-CONFIG_SERIO_RAW=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
 
 #
 # Character devices
 #
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_VT is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 
 #
 # Serial drivers
 #
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_PCI=y
-CONFIG_SERIAL_8250_NR_UARTS=4
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250 is not set
 
 #
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_TXX9=y
+CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=6
+CONFIG_SERIAL_TXX9_CONSOLE=y
+CONFIG_SERIAL_TXX9_STDSERIAL=y
 # CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
@@ -656,10 +606,7 @@
 # TPM devices
 #
 # CONFIG_TCG_TPM is not set
-
-#
-# I2C support
-#
+CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
 
 #
@@ -672,12 +619,12 @@
 # Dallas's 1-wire bus
 #
 # CONFIG_W1 is not set
+# CONFIG_HWMON is not set
 
 #
-# Hardware Monitoring support
+# Multifunction device drivers
 #
-# CONFIG_HWMON is not set
-# CONFIG_HWMON_VID is not set
+# CONFIG_MFD_SM501 is not set
 
 #
 # Multimedia devices
@@ -692,15 +639,14 @@
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
-# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
-# Console display driver support
+# Display device support
 #
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_FB is not set
 
 #
 # Sound
@@ -708,11 +654,6 @@
 # CONFIG_SOUND is not set
 
 #
-# HID Devices
-#
-# CONFIG_HID is not set
-
-#
 # USB support
 #
 CONFIG_USB_ARCH_HAS_HCD=y
@@ -728,10 +669,6 @@
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
 # CONFIG_MMC is not set
 
 #
@@ -759,7 +696,40 @@
 #
 # Real Time Clock
 #
-# CONFIG_RTC_CLASS is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1553 is not set
+CONFIG_RTC_DRV_DS1742=y
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
 
 #
 # DMA Engine support
@@ -785,9 +755,7 @@
 #
 # File systems
 #
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT2_FS is not set
 # CONFIG_EXT3_FS is not set
 # CONFIG_EXT4DEV_FS is not set
 # CONFIG_REISERFS_FS is not set
@@ -801,10 +769,10 @@
 CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
 # CONFIG_QUOTA is not set
-CONFIG_DNOTIFY=y
+# CONFIG_DNOTIFY is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-CONFIG_FUSE_FS=y
+# CONFIG_FUSE_FS is not set
 CONFIG_GENERIC_ACL=y
 
 #
@@ -824,21 +792,20 @@
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
+# CONFIG_PROC_KCORE is not set
 CONFIG_PROC_SYSCTL=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
-CONFIG_CONFIGFS_FS=y
+# CONFIG_CONFIGFS_FS is not set
 
 #
 # Miscellaneous filesystems
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
@@ -855,17 +822,17 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+# CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-CONFIG_EXPORTFS=y
+CONFIG_LOCKD_V4=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -889,10 +856,7 @@
 #
 # Distributed Lock Manager
 #
-CONFIG_DLM=y
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
-# CONFIG_DLM_DEBUG is not set
+# CONFIG_DLM is not set
 
 #
 # Profiling support
@@ -910,72 +874,29 @@
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CROSSCOMPILE=y
 CONFIG_CMDLINE=""
+CONFIG_SYS_SUPPORTS_KGDB=y
 
 #
 # Security options
 #
-CONFIG_KEYS=y
-CONFIG_KEYS_DEBUG_PROC_KEYS=y
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_XCBC=y
-CONFIG_CRYPTO_NULL=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_WP512=y
-CONFIG_CRYPTO_TGR192=y
-CONFIG_CRYPTO_GF128MUL=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_LRW=y
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_FCRYPT=y
-CONFIG_CRYPTO_BLOWFISH=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-CONFIG_CRYPTO_SERPENT=y
-CONFIG_CRYPTO_AES=y
-CONFIG_CRYPTO_CAST5=y
-CONFIG_CRYPTO_CAST6=y
-CONFIG_CRYPTO_TEA=y
-CONFIG_CRYPTO_ARC4=y
-CONFIG_CRYPTO_KHAZAD=y
-CONFIG_CRYPTO_ANUBIS=y
-CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_CRC32C=y
-CONFIG_CRYPTO_CAMELLIA=y
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO is not set
 
 #
 # Library routines
 #
 CONFIG_BITREVERSE=y
 # CONFIG_CRC_CCITT is not set
-CONFIG_CRC16=y
+# CONFIG_CRC16 is not set
 CONFIG_CRC32=y
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/mips/configs/rbhma4500_defconfig b/arch/mips/configs/rbhma4500_defconfig
index 7d0f217..41011f7 100644
--- a/arch/mips/configs/rbhma4500_defconfig
+++ b/arch/mips/configs/rbhma4500_defconfig
@@ -89,7 +89,6 @@
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_MIPS_L1_CACHE_SHIFT=5
 CONFIG_HAVE_STD_PC_SERIAL_PORT=y
-CONFIG_TOSHIBA_BOARDS=y
 
 #
 # CPU selection
diff --git a/arch/mips/configs/tb0229_defconfig b/arch/mips/configs/tb0219_defconfig
similarity index 98%
rename from arch/mips/configs/tb0229_defconfig
rename to arch/mips/configs/tb0219_defconfig
index 1756d2b..8b1675c 100644
--- a/arch/mips/configs/tb0229_defconfig
+++ b/arch/mips/configs/tb0219_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20
-# Tue Feb 20 21:47:41 2007
+# Linux kernel version: 2.6.21-rc6
+# Sun Apr 15 01:06:01 2007
 #
 CONFIG_MIPS=y
 
@@ -66,10 +66,11 @@
 # CONFIG_IBM_WORKPAD is not set
 # CONFIG_NEC_CMBVR4133 is not set
 CONFIG_TANBAC_TB022X=y
-# CONFIG_TANBAC_TB0226 is not set
-# CONFIG_TANBAC_TB0287 is not set
 # CONFIG_VICTOR_MPC30X is not set
 # CONFIG_ZAO_CAPCELLA is not set
+CONFIG_TANBAC_TB0219=y
+# CONFIG_TANBAC_TB0226 is not set
+# CONFIG_TANBAC_TB0287 is not set
 CONFIG_PCI_VR41XX=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
@@ -184,6 +185,7 @@
 # CONFIG_IKCONFIG is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
 CONFIG_EMBEDDED=y
@@ -375,7 +377,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
@@ -415,7 +417,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-# CONFIG_BLK_DEV_INITRD is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -646,7 +647,7 @@
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-CONFIG_TANBAC_TB0219=y
+CONFIG_GPIO_TB0219=y
 # CONFIG_DRM is not set
 CONFIG_GPIO_VR41XX=y
 # CONFIG_RAW_DRIVER is not set
@@ -679,6 +680,11 @@
 # CONFIG_HWMON_VID is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -692,7 +698,7 @@
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 
 #
@@ -700,7 +706,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -831,6 +836,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
diff --git a/arch/mips/kernel/early_printk.c b/arch/mips/kernel/early_printk.c
index 4fa54b2..9dccfa4 100644
--- a/arch/mips/kernel/early_printk.c
+++ b/arch/mips/kernel/early_printk.c
@@ -12,7 +12,8 @@
 
 extern void prom_putchar(char);
 
-static void early_console_write(struct console *con, const char *s, unsigned n)
+static void __init
+early_console_write(struct console *con, const char *s, unsigned n)
 {
 	while (n-- && *s) {
 		if (*s == '\n')
@@ -22,14 +23,20 @@
 	}
 }
 
-static struct console early_console = {
+static struct console early_console __initdata = {
 	.name	= "early",
 	.write	= early_console_write,
 	.flags	= CON_PRINTBUFFER | CON_BOOT,
 	.index	= -1
 };
 
+static int early_console_initialized __initdata;
+
 void __init setup_early_printk(void)
 {
+	if (early_console_initialized)
+		return;
+	early_console_initialized = 1;
+
 	register_console(&early_console);
 }
diff --git a/arch/mips/kernel/irq-msc01.c b/arch/mips/kernel/irq-msc01.c
index 2967537..410868b 100644
--- a/arch/mips/kernel/irq-msc01.c
+++ b/arch/mips/kernel/irq-msc01.c
@@ -132,11 +132,11 @@
 };
 
 
-void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq)
+void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq)
 {
 	extern void (*board_bind_eic_interrupt)(unsigned int irq, unsigned int regset);
 
-	_icctrl_msc = (unsigned long) ioremap (MIPS_MSC01_IC_REG_BASE, 0x40000);
+	_icctrl_msc = (unsigned long) ioremap (icubase, 0x40000);
 
 	/* Reset interrupt controller - initialises all registers to 0 */
 	MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT);
@@ -148,14 +148,14 @@
 
 		switch (imp->im_type) {
 		case MSC01_IRQ_EDGE:
-			set_irq_chip(base+n, &msc_edgeirq_type);
+			set_irq_chip(irqbase+n, &msc_edgeirq_type);
 			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
 			else
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
 			break;
 		case MSC01_IRQ_LEVEL:
-			set_irq_chip(base+n, &msc_levelirq_type);
+			set_irq_chip(irqbase+n, &msc_levelirq_type);
 			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
 			else
@@ -163,7 +163,7 @@
 		}
 	}
 
-	irq_base = base;
+	irq_base = irqbase;
 
 	MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT);	/* Enable interrupt generation */
 
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 2fe4c86..aeded6c 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -28,7 +28,7 @@
 
 static unsigned long irq_map[NR_IRQS / BITS_PER_LONG];
 
-int __devinit allocate_irqno(void)
+int allocate_irqno(void)
 {
 	int irq;
 
@@ -59,7 +59,7 @@
 		BUG_ON(test_and_set_bit(i, irq_map));
 }
 
-void __devinit free_irqno(unsigned int irq)
+void free_irqno(unsigned int irq)
 {
 	smp_mb__before_clear_bit();
 	clear_bit(irq, irq_map);
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index e5e56bd..751b4a1 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -306,7 +306,7 @@
 
 struct clocksource clocksource_mips = {
 	.name		= "MIPS",
-	.mask		= 0xffffffff,
+	.mask		= CLOCKSOURCE_MASK(32),
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ff45a4b..200de02 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -927,9 +927,9 @@
 	      (regs->cp0_cause & 0x7f) >> 2);
 }
 
-asmlinkage void do_default_vi(struct pt_regs *regs)
+static asmlinkage void do_default_vi(void)
 {
-	show_regs(regs);
+	show_regs(get_irq_regs());
 	panic("Caught unexpected vectored interrupt.");
 }
 
@@ -1128,7 +1128,7 @@
 	clear_bit(set, &sr->sr_allocated);
 }
 
-static void *set_vi_srs_handler(int n, void *addr, int srs)
+static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
 {
 	unsigned long handler;
 	unsigned long old_handler = vi_handlers[n];
@@ -1217,7 +1217,7 @@
 	return (void *)old_handler;
 }
 
-void *set_vi_handler(int n, void *addr)
+void *set_vi_handler(int n, vi_handler_t addr)
 {
 	return set_vi_srs_handler(n, addr, 0);
 }
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index d7d3b14..5dad13e 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -9,4 +9,4 @@
 obj-$(CONFIG_PCI)	+= iomap-pci.o
 
 # libgcc-style stuff needed in the kernel
-lib-y += ashldi3.o ashrdi3.o lshrdi3.o
+lib-y += ashldi3.o ashrdi3.o lshrdi3.o ucmpdi2.o
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
new file mode 100644
index 0000000..e9ff258
--- /dev/null
+++ b/arch/mips/lib/ucmpdi2.c
@@ -0,0 +1,19 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+word_type __ucmpdi2 (unsigned long a, unsigned long b)
+{
+	const DWunion au = {.ll = a};
+	const DWunion bu = {.ll = b};
+
+	if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
+		return 0;
+	else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
+		return 2;
+	if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
+		return 0;
+	else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
+		return 2;
+	return 1;
+}
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
index 83d7602..1cd830e 100644
--- a/arch/mips/mips-boards/malta/malta_int.c
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -311,16 +311,21 @@
 	if (!cpu_has_veic)
 		mips_cpu_irq_init();
 
-        switch(mips_revision_corid) {
-        case MIPS_REVISION_CORID_CORE_MSC:
-        case MIPS_REVISION_CORID_CORE_FPGA2:
-        case MIPS_REVISION_CORID_CORE_FPGA3:
-        case MIPS_REVISION_CORID_CORE_24K:
-        case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+        switch(mips_revision_sconid) {
+        case MIPS_REVISION_SCON_SOCIT:
+        case MIPS_REVISION_SCON_ROCIT:
 		if (cpu_has_veic)
-			init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
+			init_msc_irqs (MIPS_MSC01_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
 		else
-			init_msc_irqs (MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
+			init_msc_irqs (MIPS_MSC01_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
+		break;
+
+        case MIPS_REVISION_SCON_SOCITSC:
+        case MIPS_REVISION_SCON_SOCITSCP:
+		if (cpu_has_veic)
+			init_msc_irqs (MIPS_SOCITSC_IC_REG_BASE, MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs);
+		else
+			init_msc_irqs (MIPS_SOCITSC_IC_REG_BASE, MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs);
 	}
 
 	if (cpu_has_veic) {
diff --git a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
index 675502a..10dd2af 100644
--- a/arch/mips/mm/highmem.c
+++ b/arch/mips/mm/highmem.c
@@ -80,7 +80,6 @@
 	pagefault_enable();
 }
 
-#ifndef CONFIG_LIMITED_DMA
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
@@ -99,7 +98,6 @@
 
 	return (void*) vaddr;
 }
-#endif /* CONFIG_LIMITED_DMA */
 
 struct page *__kmap_atomic_to_page(void *ptr)
 {
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index 2d1c2c0..4c80528 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -424,9 +424,6 @@
 			continue;
 		}
 		ClearPageReserved(page);
-#ifdef CONFIG_LIMITED_DMA
-		set_page_address(page, lowmem_page_address(page));
-#endif
 		init_page_count(page);
 		__free_page(page);
 		totalhigh_pages++;
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 492c518..e714929 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -35,24 +35,24 @@
 #include <asm/smp.h>
 #include <asm/war.h>
 
-static __init int __attribute__((unused)) r45k_bvahwbug(void)
+static __init int __maybe_unused r45k_bvahwbug(void)
 {
 	/* XXX: We should probe for the presence of this bug, but we don't. */
 	return 0;
 }
 
-static __init int __attribute__((unused)) r4k_250MHZhwbug(void)
+static __init int __maybe_unused r4k_250MHZhwbug(void)
 {
 	/* XXX: We should probe for the presence of this bug, but we don't. */
 	return 0;
 }
 
-static __init int __attribute__((unused)) bcm1250_m3_war(void)
+static __init int __maybe_unused bcm1250_m3_war(void)
 {
 	return BCM1250_M3_WAR;
 }
 
-static __init int __attribute__((unused)) r10000_llsc_war(void)
+static __init int __maybe_unused r10000_llsc_war(void)
 {
 	return R10000_LLSC_WAR;
 }
@@ -511,18 +511,18 @@
 #define i_ehb(buf) i_sll(buf, 0, 0, 3)
 
 #ifdef CONFIG_64BIT
-static __init int __attribute__((unused)) in_compat_space_p(long addr)
+static __init int __maybe_unused in_compat_space_p(long addr)
 {
 	/* Is this address in 32bit compat space? */
 	return (((addr) & 0xffffffff00000000L) == 0xffffffff00000000L);
 }
 
-static __init int __attribute__((unused)) rel_highest(long val)
+static __init int __maybe_unused rel_highest(long val)
 {
 	return ((((val + 0x800080008000L) >> 48) & 0xffff) ^ 0x8000) - 0x8000;
 }
 
-static __init int __attribute__((unused)) rel_higher(long val)
+static __init int __maybe_unused rel_higher(long val)
 {
 	return ((((val + 0x80008000L) >> 32) & 0xffff) ^ 0x8000) - 0x8000;
 }
@@ -556,8 +556,8 @@
 		i_lui(buf, rs, rel_hi(addr));
 }
 
-static __init void __attribute__((unused)) i_LA(u32 **buf, unsigned int rs,
-						long addr)
+static __init void __maybe_unused i_LA(u32 **buf, unsigned int rs,
+					     long addr)
 {
 	i_LA_mostly(buf, rs, addr);
 	if (rel_lo(addr))
@@ -636,8 +636,8 @@
 	move_labels(lab, first, end, off);
 }
 
-static __init int __attribute__((unused)) insn_has_bdelay(struct reloc *rel,
-							  u32 *addr)
+static __init int __maybe_unused insn_has_bdelay(struct reloc *rel,
+						       u32 *addr)
 {
 	for (; rel->lab != label_invalid; rel++) {
 		if (rel->addr == addr
@@ -650,15 +650,15 @@
 }
 
 /* convenience functions for labeled branches */
-static void __init __attribute__((unused))
+static void __init __maybe_unused
 	il_bltz(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
 {
 	r_mips_pc16(r, *p, l);
 	i_bltz(p, reg, 0);
 }
 
-static void __init __attribute__((unused)) il_b(u32 **p, struct reloc **r,
-					 enum label_id l)
+static void __init __maybe_unused il_b(u32 **p, struct reloc **r,
+					     enum label_id l)
 {
 	r_mips_pc16(r, *p, l);
 	i_b(p, 0);
@@ -671,7 +671,7 @@
 	i_beqz(p, reg, 0);
 }
 
-static void __init __attribute__((unused))
+static void __init __maybe_unused
 il_beqzl(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
 {
 	r_mips_pc16(r, *p, l);
@@ -692,7 +692,7 @@
 	i_bgezl(p, reg, 0);
 }
 
-static void __init __attribute__((unused))
+static void __init __maybe_unused
 il_bgez(u32 **p, struct reloc **r, unsigned int reg, enum label_id l)
 {
 	r_mips_pc16(r, *p, l);
@@ -810,7 +810,7 @@
  *
  * As if we MIPS hackers wouldn't know how to nop pipelines happy ...
  */
-static __init void __attribute__((unused)) build_tlb_probe_entry(u32 **p)
+static __init void __maybe_unused build_tlb_probe_entry(u32 **p)
 {
 	switch (current_cpu_data.cputype) {
 	/* Found by experiment: R4600 v2.0 needs this, too.  */
@@ -1098,7 +1098,7 @@
  * TMP and PTR are scratch.
  * TMP will be clobbered, PTR will hold the pgd entry.
  */
-static __init void __attribute__((unused))
+static __init void __maybe_unused
 build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr)
 {
 	long pgdc = (long)pgd_current;
diff --git a/arch/mips/momentum/Kconfig b/arch/mips/momentum/Kconfig
deleted file mode 100644
index 70a61cf..0000000
--- a/arch/mips/momentum/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-config JAGUAR_DMALOW
-	bool "Low DMA Mode"
-	depends on MOMENCO_JAGUAR_ATX
-	help
-	  Select to Y if jump JP5 is set on your board, N otherwise.  Normally
-	  the jumper is set, so if you feel unsafe, just say Y.
diff --git a/arch/mips/momentum/jaguar_atx/Makefile b/arch/mips/momentum/jaguar_atx/Makefile
deleted file mode 100644
index 2e8cebd..0000000
--- a/arch/mips/momentum/jaguar_atx/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# Makefile for Momentum Computer's Jaguar-ATX board.
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-obj-y += irq.o platform.o prom.o reset.o setup.o
-
-obj-$(CONFIG_SERIAL_8250_CONSOLE) += ja-console.o
-obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o
diff --git a/arch/mips/momentum/jaguar_atx/dbg_io.c b/arch/mips/momentum/jaguar_atx/dbg_io.c
deleted file mode 100644
index b85a652..0000000
--- a/arch/mips/momentum/jaguar_atx/dbg_io.c
+++ /dev/null
@@ -1,125 +0,0 @@
-
-#if defined(CONFIG_REMOTE_DEBUG)
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define         UART16550_BAUD_2400             2400
-#define         UART16550_BAUD_4800             4800
-#define         UART16550_BAUD_9600             9600
-#define         UART16550_BAUD_19200            19200
-#define         UART16550_BAUD_38400            38400
-#define         UART16550_BAUD_57600            57600
-#define         UART16550_BAUD_115200           115200
-
-#define         UART16550_PARITY_NONE           0
-#define         UART16550_PARITY_ODD            0x08
-#define         UART16550_PARITY_EVEN           0x18
-#define         UART16550_PARITY_MARK           0x28
-#define         UART16550_PARITY_SPACE          0x38
-
-#define         UART16550_DATA_5BIT             0x0
-#define         UART16550_DATA_6BIT             0x1
-#define         UART16550_DATA_7BIT             0x2
-#define         UART16550_DATA_8BIT             0x3
-
-#define         UART16550_STOP_1BIT             0x0
-#define         UART16550_STOP_2BIT             0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define         BASE                    OCELOT_SERIAL1_BASE
-#define         MAX_BAUD                OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define         REG_OFFSET              4
-
-/* register offset */
-#define         OFS_RCV_BUFFER          0
-#define         OFS_TRANS_HOLD          0
-#define         OFS_SEND_BUFFER         0
-#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
-#define         OFS_INTR_ID             (2*REG_OFFSET)
-#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
-#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
-#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
-#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
-#define         OFS_LINE_STATUS         (5*REG_OFFSET)
-#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
-#define         OFS_RS232_INPUT         (6*REG_OFFSET)
-#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
-
-#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
-#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
-#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
-	/* disable interrupts */
-	UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
-	/* set up baud rate */
-	{
-		uint32 divisor;
-
-		/* set DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
-		/* set divisor */
-		divisor = MAX_BAUD / baud;
-		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
-		/* clear DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-	}
-
-	/* set data format */
-	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-	return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
-	UART16550_WRITE(OFS_SEND_BUFFER, byte);
-	return 1;
-}
-
-#endif
diff --git a/arch/mips/momentum/jaguar_atx/irq.c b/arch/mips/momentum/jaguar_atx/irq.c
deleted file mode 100644
index f2b4325..0000000
--- a/arch/mips/momentum/jaguar_atx/irq.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2002 Momentum Computer, Inc.
- * Author: Matthew Dharm, mdharm@momenco.com
- *
- * Based on work by:
- *   Copyright (C) 2000 RidgeRun, Inc.
- *   Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- *   Copyright 2001 MontaVista Software Inc.
- *   Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- *   Copyright (C) 2000, 01, 06 Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/time.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status();
-
-	if (pending & STATUSF_IP0)
-		do_IRQ(0);
-	else if (pending & STATUSF_IP1)
-		do_IRQ(1);
-	else if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(3);
-	else if (pending & STATUSF_IP4)
-		do_IRQ(4);
-	else if (pending & STATUSF_IP5)
-		do_IRQ(5);
-	else if (pending & STATUSF_IP6)
-		do_IRQ(6);
-	else if (pending & STATUSF_IP7)
-		ll_timer_interrupt(7);
-	else {
-		/*
-		 * Now look at the extended interrupts
-		 */
-		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-		if (pending & STATUSF_IP8)
-			ll_mv64340_irq();
-	}
-}
-
-static struct irqaction cascade_mv64340 = {
-	no_action, IRQF_DISABLED, CPU_MASK_NONE, "MV64340-Cascade", NULL, NULL
-};
-
-void __init arch_init_irq(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * int-handler is not on bootstrap
-	 */
-	clear_c0_status(ST0_IM);
-
-	mips_cpu_irq_init();
-	rm7k_cpu_irq_init();
-
-	/* set up the cascading interrupts */
-	setup_irq(8, &cascade_mv64340);
-
-	mv64340_irq_init(16);
-
-	set_c0_status(ST0_IM);
-}
diff --git a/arch/mips/momentum/jaguar_atx/ja-console.c b/arch/mips/momentum/jaguar_atx/ja-console.c
deleted file mode 100644
index 2c30b4f..0000000
--- a/arch/mips/momentum/jaguar_atx/ja-console.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001, 2002, 2004 Ralf Baechle
- */
-#include <linux/init.h>
-#include <linux/console.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/termios.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <asm/serial.h>
-
-/* SUPERIO uart register map */
-struct ja_uartregs {
-	union {
-		volatile u8	pad0[3];
-		volatile u8	rbr;	/* read only, DLAB == 0 */
-		volatile u8	pad1[3];
-		volatile u8	thr;	/* write only, DLAB == 0 */
-		volatile u8	pad2[3];
-		volatile u8	dll;	/* DLAB == 1 */
-	} u1;
-	union {
-		volatile u8	pad0[3];
-		volatile u8	ier;	/* DLAB == 0 */
-		volatile u8	pad1[3];
-		volatile u8	dlm;	/* DLAB == 1 */
-	} u2;
-	union {
-		volatile u8	pad0[3];
-		volatile u8	iir;	/* read only */
-		volatile u8	pad1[3];
-		volatile u8	fcr;	/* write only */
-	} u3;
-	volatile u8	pad0[3];
-	volatile u8	iu_lcr;
-	volatile u8	pad1[3];
-	volatile u8	iu_mcr;
-	volatile u8	pad2[3];
-	volatile u8	iu_lsr;
-	volatile u8	pad3[3];
-	volatile u8	iu_msr;
-	volatile u8	pad4[3];
-	volatile u8	iu_scr;
-} ja_uregs_t;
-
-#define iu_rbr u1.rbr
-#define iu_thr u1.thr
-#define iu_dll u1.dll
-#define iu_ier u2.ier
-#define iu_dlm u2.dlm
-#define iu_iir u3.iir
-#define iu_fcr u3.fcr
-
-extern unsigned long uart_base;
-
-static inline struct ja_uartregs *console_uart(void)
-{
-	return (struct ja_uartregs *) (uart_base + 0x23UL);
-}
-
-void prom_putchar(char c)
-{
-	struct ja_uartregs *uart = console_uart();
-
-	while ((uart->iu_lsr & 0x20) == 0);
-	uart->iu_thr = c;
-}
-
-static void inline ja_console_probe(void)
-{
-	struct uart_port up;
-
-	/*
-	 * Register to interrupt zero because we share the interrupt with
-	 * the serial driver which we don't properly support yet.
-	 */
-	memset(&up, 0, sizeof(up));
-	up.membase	= (unsigned char *) uart_base + 0x23UL;
-	up.irq		= JAGUAR_ATX_SERIAL1_IRQ;
-	up.uartclk	= JAGUAR_ATX_UART_CLK;
-	up.regshift	= 2;
-	up.iotype	= UPIO_MEM;
-	up.flags	= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	up.line		= 0;
-
-	if (early_serial_setup(&up))
-		printk(KERN_ERR "Early serial init of port 0 failed\n");
-}
-
-__init void ja_setup_console(void)
-{
-	ja_console_probe();
-}
diff --git a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h b/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
deleted file mode 100644
index 022f697..0000000
--- a/arch/mips/momentum/jaguar_atx/jaguar_atx_fpga.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Jaguar-ATX Board Register Definitions
- *
- * (C) 2002 Momentum Computer Inc.
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#ifndef __JAGUAR_ATX_FPGA_H__
-#define __JAGUAR_ATX_FPGA_H__
-
-#define JAGUAR_ATX_REG_BOARDREV		0x0
-#define JAGUAR_ATX_REG_FPGA_REV		0x1
-#define JAGUAR_ATX_REG_FPGA_TYPE	0x2
-#define JAGUAR_ATX_REG_RESET_STATUS	0x3
-#define JAGUAR_ATX_REG_BOARD_STATUS	0x4
-#define JAGUAR_ATX_REG_RESERVED1	0x5
-#define JAGUAR_ATX_REG_SET		0x6
-#define JAGUAR_ATX_REG_CLR		0x7
-#define JAGUAR_ATX_REG_EEPROM_MODE	0x9
-#define JAGUAR_ATX_REG_RESERVED2	0xa
-#define JAGUAR_ATX_REG_RESERVED3	0xb
-#define JAGUAR_ATX_REG_RESERVED4	0xc
-#define JAGUAR_ATX_REG_PHY_INTSTAT	0xd
-#define JAGUAR_ATX_REG_RESERVED5	0xe
-#define JAGUAR_ATX_REG_RESERVED6	0xf
-
-#define JAGUAR_ATX_CS0_ADDR		0xfc000000L
-
-extern unsigned long ja_fpga_base;
-
-#define __FPGA_REG_TO_ADDR(reg)						\
-	((void *) ja_fpga_base + JAGUAR_ATX_REG_##reg)
-#define JAGUAR_FPGA_WRITE(x, reg) writeb(x, __FPGA_REG_TO_ADDR(reg))
-#define JAGUAR_FPGA_READ(reg) readb(__FPGA_REG_TO_ADDR(reg))
-
-#endif
diff --git a/arch/mips/momentum/jaguar_atx/platform.c b/arch/mips/momentum/jaguar_atx/platform.c
deleted file mode 100644
index 5618448..0000000
--- a/arch/mips/momentum/jaguar_atx/platform.c
+++ /dev/null
@@ -1,208 +0,0 @@
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/ioport.h>
-#include <linux/mv643xx.h>
-#include <linux/platform_device.h>
-
-#include "jaguar_atx_fpga.h"
-
-#if defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE)
-
-static struct resource mv643xx_eth_shared_resources[] = {
-	[0] = {
-		.name   = "ethernet shared base",
-		.start  = 0xf1000000 + MV643XX_ETH_SHARED_REGS,
-		.end    = 0xf1000000 + MV643XX_ETH_SHARED_REGS +
-		                       MV643XX_ETH_SHARED_REGS_SIZE - 1,
-		.flags  = IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device mv643xx_eth_shared_device = {
-	.name		= MV643XX_ETH_SHARED_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv643xx_eth_shared_resources),
-	.resource	= mv643xx_eth_shared_resources,
-};
-
-#define MV_SRAM_BASE			0xfe000000UL
-#define MV_SRAM_SIZE			(256 * 1024)
-
-#define MV_SRAM_RXRING_SIZE		(MV_SRAM_SIZE / 4)
-#define MV_SRAM_TXRING_SIZE		(MV_SRAM_SIZE / 4)
-
-#define MV_SRAM_BASE_ETH0		MV_SRAM_BASE
-#define MV_SRAM_BASE_ETH1		(MV_SRAM_BASE + (MV_SRAM_SIZE / 2))
-
-#define MV64x60_IRQ_ETH_0 48
-#define MV64x60_IRQ_ETH_1 49
-#define MV64x60_IRQ_ETH_2 50
-
-static struct resource mv64x60_eth0_resources[] = {
-	[0] = {
-		.name	= "eth0 irq",
-		.start	= MV64x60_IRQ_ETH_0,
-		.end	= MV64x60_IRQ_ETH_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth0_pd = {
-	.port_number	= 0,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH0,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH0 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth0_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
-	.resource	= mv64x60_eth0_resources,
-	.dev = {
-		.platform_data = &eth0_pd,
-	},
-};
-
-static struct resource mv64x60_eth1_resources[] = {
-	[0] = {
-		.name	= "eth1 irq",
-		.start	= MV64x60_IRQ_ETH_1,
-		.end	= MV64x60_IRQ_ETH_1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth1_pd = {
-	.port_number	= 1,
-
-	.tx_sram_addr	= MV_SRAM_BASE_ETH1,
-	.tx_sram_size	= MV_SRAM_TXRING_SIZE,
-	.tx_queue_size	= MV_SRAM_TXRING_SIZE / 16,
-
-	.rx_sram_addr	= MV_SRAM_BASE_ETH1 + MV_SRAM_TXRING_SIZE,
-	.rx_sram_size	= MV_SRAM_RXRING_SIZE,
-	.rx_queue_size	= MV_SRAM_RXRING_SIZE / 16,
-};
-
-static struct platform_device eth1_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
-	.resource	= mv64x60_eth1_resources,
-	.dev = {
-		.platform_data = &eth1_pd,
-	},
-};
-
-static struct resource mv64x60_eth2_resources[] = {
-	[0] = {
-		.name	= "eth2 irq",
-		.start	= MV64x60_IRQ_ETH_2,
-		.end	= MV64x60_IRQ_ETH_2,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct mv643xx_eth_platform_data eth2_pd = {
-	.port_number	= 2,
-};
-
-static struct platform_device eth2_device = {
-	.name		= MV643XX_ETH_NAME,
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
-	.resource	= mv64x60_eth2_resources,
-	.dev = {
-		.platform_data = &eth2_pd,
-	},
-};
-
-static struct platform_device *mv643xx_eth_pd_devs[] __initdata = {
-	&mv643xx_eth_shared_device,
-	&eth0_device,
-	&eth1_device,
-	&eth2_device,
-};
-
-static u8 __init exchange_bit(u8 val, u8 cs)
-{
-	/* place the data */
-	JAGUAR_FPGA_WRITE((val << 2) | cs, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock on */
-	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE);
-	udelay(1);
-
-	/* turn the clock off and read-strobe */
-	JAGUAR_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE);
-
-	/* return the data */
-	return (JAGUAR_FPGA_READ(EEPROM_MODE) >> 3) & 0x1;
-}
-
-static void __init get_mac(char dest[6])
-{
-	u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	int i,j;
-
-	for (i = 0; i < 12; i++)
-		exchange_bit(read_opcode[i], 1);
-
-	for (j = 0; j < 6; j++) {
-		dest[j] = 0;
-		for (i = 0; i < 8; i++) {
-			dest[j] <<= 1;
-			dest[j] |= exchange_bit(0, 1);
-		}
-	}
-
-	/* turn off CS */
-	exchange_bit(0,0);
-}
-
-/*
- * Copy and increment ethernet MAC address by a small value.
- *
- * This is useful for systems where the only one MAC address is stored in
- * non-volatile memory for multiple ports.
- */
-static inline void eth_mac_add(unsigned char *dst, unsigned char *src,
-	unsigned int add)
-{
-	int i;
-
-	BUG_ON(add >= 256);
-
-	for (i = ETH_ALEN; i >= 0; i--) {
-		dst[i] = src[i] + add;
-		add = dst[i] < src[i];		/* compute carry */
-	}
-
-	WARN_ON(add);
-}
-
-static int __init mv643xx_eth_add_pds(void)
-{
-	unsigned char mac[ETH_ALEN];
-	int ret;
-
-	get_mac(mac);
-	eth_mac_add(eth0_pd.mac_addr, mac, 0);
-	eth_mac_add(eth1_pd.mac_addr, mac, 1);
-	eth_mac_add(eth2_pd.mac_addr, mac, 2);
-	ret = platform_add_devices(mv643xx_eth_pd_devs,
-			ARRAY_SIZE(mv643xx_eth_pd_devs));
-
-	return ret;
-}
-
-device_initcall(mv643xx_eth_add_pds);
-
-#endif /* defined(CONFIG_MV643XX_ETH) || defined(CONFIG_MV643XX_ETH_MODULE) */
diff --git a/arch/mips/momentum/jaguar_atx/prom.c b/arch/mips/momentum/jaguar_atx/prom.c
deleted file mode 100644
index 5dd154e..0000000
--- a/arch/mips/momentum/jaguar_atx/prom.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com  [MIPS64 modifications]
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Added changes for SMP - Manish Lachwani (lachwani@pmc-sierra.com)
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-#include <linux/mv643xx.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-
-#include "jaguar_atx_fpga.h"
-
-extern void ja_setup_console(void);
-
-struct callvectors *debug_vectors;
-
-extern unsigned long cpu_clock;
-
-const char *get_system_type(void)
-{
-	return "Momentum Jaguar-ATX";
-}
-
-#ifdef CONFIG_64BIT
-
-unsigned long signext(unsigned long addr)
-{
-	addr &= 0xffffffff;
-	return (unsigned long)((int)addr);
-}
-
-void *get_arg(unsigned long args, int arc)
-{
-	unsigned long ul;
-	unsigned char *puc, uc;
-
-	args += (arc * 4);
-	ul = (unsigned long)signext(args);
-	puc = (unsigned char *)ul;
-	if (puc == 0)
-		return (void *)0;
-
-#ifdef CONFIG_CPU_LITTLE_ENDIAN
-	uc = *puc++;
-	l = (unsigned long)uc;
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 8);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 16);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 24);
-#else
-	uc = *puc++;
-	ul = ((unsigned long)uc) << 24;
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 16);
-	uc = *puc++;
-	ul |= (((unsigned long)uc) << 8);
-	uc = *puc++;
-	ul |= ((unsigned long)uc);
-#endif
-	ul = signext(ul);
-
-	return (void *)ul;
-}
-
-char *arg64(unsigned long addrin, int arg_index)
-{
-	unsigned long args;
-	char *p;
-
-	args = signext(addrin);
-	p = (char *)get_arg(args, arg_index);
-
-	return p;
-}
-#endif  /* CONFIG_64BIT */
-
-/* PMON passes arguments in C main() style */
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **arg = (char **) fw_arg1;
-	char **env = (char **) fw_arg2;
-	struct callvectors *cv = (struct callvectors *) fw_arg3;
-	int i;
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-//	ja_setup_console();	/* The very first thing.  */
-#endif
-
-#ifdef CONFIG_64BIT
-	char *ptr;
-
-	printk("Mips64 Jaguar-ATX\n");
-	/* save the PROM vectors for debugging use */
-	debug_vectors = (struct callvectors *)signext((unsigned long)cv);
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-
-	for (i = 1; i < argc; i++) {
-		ptr = (char *)arg64((unsigned long)arg, i);
-		if ((strlen(arcs_cmdline) + strlen(ptr) + 1) >=
-		    sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, ptr);
-		strcat(arcs_cmdline, " ");
-	}
-
-	i = 0;
-	while (1) {
-		ptr = (char *)arg64((unsigned long)env, i);
-		if (! ptr)
-			break;
-
-		if (strncmp("gtbase", ptr, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(ptr + strlen("gtbase="),
-							NULL, 16);
-
-			if ((marvell_base & 0xffffffff00000000) == 0)
-				marvell_base |= 0xffffffff00000000;
-
-			printk("marvell_base set to 0x%016lx\n", marvell_base);
-		}
-		if (strncmp("cpuclock", ptr, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(ptr + strlen("cpuclock="),
-							NULL, 10);
-			printk("cpu_clock set to %d\n", cpu_clock);
-		}
-		i++;
-	}
-	printk("arcs_cmdline: %s\n", arcs_cmdline);
-
-#else   /* CONFIG_64BIT */
-	/* save the PROM vectors for debugging use */
-	debug_vectors = cv;
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
-		    >= sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, arg[i]);
-		strcat(arcs_cmdline, " ");
-	}
-
-	while (*env) {
-		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(*env + strlen("gtbase="),
-							NULL, 16);
-		}
-		if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) {
-			cpu_clock = simple_strtol(*env + strlen("cpuclock="),
-							NULL, 10);
-		}
-		env++;
-	}
-#endif /* CONFIG_64BIT */
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_JAGUAR_ATX;
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
-
-void __init prom_fixup_mem_map(unsigned long start, unsigned long end)
-{
-}
-
-int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp)
-{
-	/* Clear the semaphore */
-	*(volatile uint32_t *)(0xbb000a68) = 0x80000000;
-
-	return 1;
-}
-
-void prom_init_secondary(void)
-{
-        clear_c0_config(CONF_CM_CMASK);
-        set_c0_config(0x2);
-
-	clear_c0_status(ST0_IM);
-	set_c0_status(0x1ffff);
-}
-
-void prom_smp_finish(void)
-{
-}
diff --git a/arch/mips/momentum/jaguar_atx/reset.c b/arch/mips/momentum/jaguar_atx/reset.c
deleted file mode 100644
index c73b089..0000000
--- a/arch/mips/momentum/jaguar_atx/reset.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * Copyright (C) 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Louis Hamilton, Red Hat, Inc.
- * hamilton@redhat.com  [MIPS64 modifications]
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_jaguar_restart(char *command)
-{
-	/* base address of timekeeper portion of part */
-#ifdef CONFIG_64BIT
-	void *nvram = (void*) 0xfffffffffc807000;
-#else
-	void *nvram = (void*) 0xfc807000;
-#endif
-	/* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */
-	writeb(0x84, nvram + 0xff7);
-
-	/* wait for the watchdog to go off */
-	mdelay(100+(1000/16));
-
-	/* if the watchdog fails for some reason, let people know */
-	printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_jaguar_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void momenco_jaguar_power_off(void)
-{
-	momenco_jaguar_halt();
-}
diff --git a/arch/mips/momentum/jaguar_atx/setup.c b/arch/mips/momentum/jaguar_atx/setup.c
deleted file mode 100644
index 5a51014..0000000
--- a/arch/mips/momentum/jaguar_atx/setup.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Jaguar-ATX board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001, 04, 06  Ralf Baechle (ralf@linux-mips.org)
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- *   mdharm@momenco.com
- *
- * Louis Hamilton, Red Hat, Inc.
- *   hamilton@redhat.com  [MIPS64 modifications]
- *
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/bootmem.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/pm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-#include <linux/mv643xx.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/tlbflush.h>
-
-#include "jaguar_atx_fpga.h"
-
-extern unsigned long mv64340_sram_base;
-unsigned long cpu_clock;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_jaguar_restart(char *command);
-extern void momenco_jaguar_halt(void);
-extern void momenco_jaguar_power_off(void);
-
-void momenco_time_init(void);
-
-static char reset_reason;
-
-static inline unsigned long ENTRYLO(unsigned long paddr)
-{
-	return ((paddr & PAGE_MASK) |
-	       (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
-		_CACHE_UNCACHED)) >> 6;
-}
-
-void __init bus_error_init(void) { /* nothing */ }
-
-/*
- * Load a few TLB entries for the MV64340 and perhiperals. The MV64340 is going
- * to be hit on every IRQ anyway - there's absolutely no point in letting it be
- * a random TLB entry, as it'll just cause needless churning of the TLB. And we
- * use the other half for the serial port, which is just a PITA otherwise :)
- *
- *	Device			Physical	Virtual
- *	MV64340 Internal Regs	0xf4000000	0xf4000000
- *	Ocelot-C[S] PLD (CS0)	0xfc000000	0xfc000000
- *	NVRAM (CS1)		0xfc800000	0xfc800000
- *	UARTs (CS2)		0xfd000000	0xfd000000
- *	Internal SRAM		0xfe000000	0xfe000000
- *	M-Systems DOC (CS3)	0xff000000	0xff000000
- */
-
-static __init void wire_stupidity_into_tlb(void)
-{
-#ifdef CONFIG_32BIT
-	write_c0_wired(0);
-	local_flush_tlb_all();
-
-	/* marvell and extra space */
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000),
-	                0xf4000000UL, PM_64K);
-	/* fpga, rtc, and uart */
-	add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000),
-	                0xfc000000UL, PM_16M);
-//	/* m-sys and internal SRAM */
-//	add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000),
-//	                0xfe000000UL, PM_16M);
-
-	marvell_base = 0xf4000000;
-	//mv64340_sram_base = 0xfe000000;	/* Currently unused */
-#endif
-}
-
-unsigned long marvell_base	= 0xf4000000L;
-unsigned long ja_fpga_base	= JAGUAR_ATX_CS0_ADDR;
-unsigned long uart_base		= 0xfd000000L;
-static unsigned char *rtc_base	= (unsigned char*) 0xfc800000L;
-
-EXPORT_SYMBOL(marvell_base);
-
-static __init int per_cpu_mappings(void)
-{
-	marvell_base	= (unsigned long) ioremap(0xf4000000, 0x10000);
-	ja_fpga_base	= (unsigned long) ioremap(JAGUAR_ATX_CS0_ADDR,  0x1000);
-	uart_base	= (unsigned long) ioremap(0xfd000000UL, 0x1000);
-	rtc_base	= ioremap(0xfc000000UL, 0x8000);
-	// ioremap(0xfe000000,  32 << 20);
-	write_c0_wired(0);
-	local_flush_tlb_all();
-	ja_setup_console();
-
-	return 0;
-}
-arch_initcall(per_cpu_mappings);
-
-unsigned long m48t37y_get_time(void)
-{
-	unsigned int year, month, day, hour, min, sec;
-	unsigned long flags;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* stop the update */
-	rtc_base[0x7ff8] = 0x40;
-
-	year = BCD2BIN(rtc_base[0x7fff]);
-	year += BCD2BIN(rtc_base[0x7ff1]) * 100;
-
-	month = BCD2BIN(rtc_base[0x7ffe]);
-
-	day = BCD2BIN(rtc_base[0x7ffd]);
-
-	hour = BCD2BIN(rtc_base[0x7ffb]);
-	min = BCD2BIN(rtc_base[0x7ffa]);
-	sec = BCD2BIN(rtc_base[0x7ff9]);
-
-	/* start the update */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return mktime(year, month, day, hour, min, sec);
-}
-
-int m48t37y_set_time(unsigned long sec)
-{
-	struct rtc_time tm;
-	unsigned long flags;
-
-	/* convert to a more useful format -- note months count from 0 */
-	to_tm(sec, &tm);
-	tm.tm_mon += 1;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	/* enable writing */
-	rtc_base[0x7ff8] = 0x80;
-
-	/* year */
-	rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100);
-	rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100);
-
-	/* month */
-	rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon);
-
-	/* day */
-	rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday);
-
-	/* hour/min/sec */
-	rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour);
-	rtc_base[0x7ffa] = BIN2BCD(tm.tm_min);
-	rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec);
-
-	/* day of week -- not really used, but let's keep it up-to-date */
-	rtc_base[0x7ffc] = BIN2BCD(tm.tm_wday + 1);
-
-	/* disable writing */
-	rtc_base[0x7ff8] = 0x00;
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-	setup_irq(8, irq);
-}
-
-/*
- * Ugly but the least of all evils.  TLB initialization did flush the TLB so
- * We need to setup mappings again before we can touch the RTC.
- */
-void momenco_time_init(void)
-{
-	wire_stupidity_into_tlb();
-
-	mips_hpt_frequency = cpu_clock / 2;
-
-	rtc_mips_get_time = m48t37y_get_time;
-	rtc_mips_set_time = m48t37y_set_time;
-}
-
-static struct resource mv_pci_io_mem0_resource = {
-	.name	= "MV64340 PCI0 IO MEM",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem0_resource = {
-	.name	= "MV64340 PCI0 MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus0_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &mv_pci_mem0_resource,
-		.io_resource	= &mv_pci_io_mem0_resource,
-	},
-	.config_addr	= MV64340_PCI_0_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static uint32_t mv_io_base, mv_io_size;
-
-static void ja_pci0_init(void)
-{
-	uint32_t mem0_base, mem0_size;
-	uint32_t io_base, io_size;
-
-	io_base = MV_READ(MV64340_PCI_0_IO_BASE_ADDR) << 16;
-	io_size = (MV_READ(MV64340_PCI_0_IO_SIZE) + 1) << 16;
-	mem0_base = MV_READ(MV64340_PCI_0_MEMORY0_BASE_ADDR) << 16;
-	mem0_size = (MV_READ(MV64340_PCI_0_MEMORY0_SIZE) + 1) << 16;
-
-	mv_pci_io_mem0_resource.start		= 0;
-	mv_pci_io_mem0_resource.end		= io_size - 1;
-	mv_pci_mem0_resource.start		= mem0_base;
-	mv_pci_mem0_resource.end		= mem0_base + mem0_size - 1;
-	mv_bus0_controller.pcic.mem_offset	= mem0_base;
-	mv_bus0_controller.pcic.io_offset	= 0;
-
-	ioport_resource.end		= io_size - 1;
-
-	register_pci_controller(&mv_bus0_controller.pcic);
-
-	mv_io_base = io_base;
-	mv_io_size = io_size;
-}
-
-static struct resource mv_pci_io_mem1_resource = {
-	.name	= "MV64340 PCI1 IO MEM",
-	.flags	= IORESOURCE_IO
-};
-
-static struct resource mv_pci_mem1_resource = {
-	.name	= "MV64340 PCI1 MEM",
-	.flags	= IORESOURCE_MEM
-};
-
-static struct mv_pci_controller mv_bus1_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &mv_pci_mem1_resource,
-		.io_resource	= &mv_pci_io_mem1_resource,
-	},
-	.config_addr	= MV64340_PCI_1_CONFIG_ADDR,
-	.config_vreg	= MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG,
-};
-
-static __init void ja_pci1_init(void)
-{
-	uint32_t mem0_base, mem0_size;
-	uint32_t io_base, io_size;
-
-	io_base = MV_READ(MV64340_PCI_1_IO_BASE_ADDR) << 16;
-	io_size = (MV_READ(MV64340_PCI_1_IO_SIZE) + 1) << 16;
-	mem0_base = MV_READ(MV64340_PCI_1_MEMORY0_BASE_ADDR) << 16;
-	mem0_size = (MV_READ(MV64340_PCI_1_MEMORY0_SIZE) + 1) << 16;
-
-	/*
-	 * Here we assume the I/O window of second bus to be contiguous with
-	 * the first.  A gap is no problem but would waste address space for
-	 * remapping the port space.
-	 */
-	mv_pci_io_mem1_resource.start		= mv_io_size;
-	mv_pci_io_mem1_resource.end		= mv_io_size + io_size - 1;
-	mv_pci_mem1_resource.start		= mem0_base;
-	mv_pci_mem1_resource.end		= mem0_base + mem0_size - 1;
-	mv_bus1_controller.pcic.mem_offset	= mem0_base;
-	mv_bus1_controller.pcic.io_offset	= 0;
-
-	ioport_resource.end		= io_base + io_size -mv_io_base - 1;
-
-	register_pci_controller(&mv_bus1_controller.pcic);
-
-	mv_io_size = io_base + io_size - mv_io_base;
-}
-
-static __init int __init ja_pci_init(void)
-{
-	unsigned long io_v_base;
-	uint32_t enable;
-
-	enable = ~MV_READ(MV64340_BASE_ADDR_ENABLE);
-
-	/*
-	 * We require at least one enabled I/O or PCI memory window or we
-	 * will ignore this PCI bus.  We ignore PCI windows 1, 2 and 3.
-	 */
-	if (enable & (0x01 <<  9) || enable & (0x01 << 10))
-		ja_pci0_init();
-
-	if (enable & (0x01 << 14) || enable & (0x01 << 15))
-		ja_pci1_init();
-
-	if (mv_io_size) {
-		io_v_base = (unsigned long) ioremap(mv_io_base, mv_io_size);
-		if (!io_v_base)
-			panic("Could not ioremap I/O port range");
-
-		set_io_port_base(io_v_base);
-	}
-
-	return 0;
-}
-
-arch_initcall(ja_pci_init);
-
-void __init plat_mem_setup(void)
-{
-	unsigned int tmpword;
-
-	board_time_init = momenco_time_init;
-
-	_machine_restart = momenco_jaguar_restart;
-	_machine_halt = momenco_jaguar_halt;
-	pm_power_off = momenco_jaguar_power_off;
-
-	/*
-	 * initrd_start = (unsigned long)jaguar_initrd_start;
-	 * initrd_end = (unsigned long)jaguar_initrd_start + (ulong)jaguar_initrd_size;
-	 * initrd_below_start_ok = 1;
-	 */
-
-	wire_stupidity_into_tlb();
-
-	/*
-	 * shut down ethernet ports, just to be sure our memory doesn't get
-	 * corrupted by random ethernet traffic.
-	 */
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8);
-	MV_WRITE(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2), 0xff << 8);
-	while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff);
-	while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff);
-	while (MV_READ(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(2)) & 0xff);
-	while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff);
-	while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff);
-	while (MV_READ(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(2)) & 0xff);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1);
-	MV_WRITE(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2),
-	         MV_READ(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(2)) & ~1);
-
-	/* Turn off the Bit-Error LED */
-	JAGUAR_FPGA_WRITE(0x80, CLR);
-
-	tmpword = JAGUAR_FPGA_READ(BOARDREV);
-	if (tmpword < 26)
-		printk("Momentum Jaguar-ATX: Board Assembly Rev. %c\n",
-			'A'+tmpword);
-	else
-		printk("Momentum Jaguar-ATX: Board Assembly Revision #0x%x\n",
-			tmpword);
-
-	tmpword = JAGUAR_FPGA_READ(FPGA_REV);
-	printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = JAGUAR_FPGA_READ(RESET_STATUS);
-	printk("Reset reason: 0x%x\n", tmpword);
-	switch (tmpword) {
-	case 0x1:
-		printk("  - Power-up reset\n");
-		break;
-	case 0x2:
-		printk("  - Push-button reset\n");
-		break;
-	case 0x8:
-		printk("  - Watchdog reset\n");
-		break;
-	case 0x10:
-		printk("  - JTAG reset\n");
-		break;
-	default:
-		printk("  - Unknown reset cause\n");
-	}
-	reset_reason = tmpword;
-	JAGUAR_FPGA_WRITE(0xff, RESET_STATUS);
-
-	tmpword = JAGUAR_FPGA_READ(BOARD_STATUS);
-	printk("Board Status register: 0x%02x\n", tmpword);
-	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
-	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-
-	/* 256MiB of RM9000x2 DDR */
-//	add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM);
-
-	/* 128MiB of MV-64340 DDR */
-//	add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
-
-	/* XXX Memory configuration should be picked up from PMON2k */
-#ifdef CONFIG_JAGUAR_DMALOW
-	printk("Jaguar ATX DMA-low mode set\n");
-	add_memory_region(0x00000000, 0x08000000, BOOT_MEM_RAM);
-	add_memory_region(0x08000000, 0x10000000, BOOT_MEM_RAM);
-#else
-	/* 128MiB of MV-64340 DDR RAM */
-	printk("Jaguar ATX DMA-low mode is not set\n");
-	add_memory_region(0x100<<20, 0x80<<20, BOOT_MEM_RAM);
-#endif
-
-#ifdef GEMDEBUG_TRACEBUFFER
-	{
-	  unsigned int tbControl;
-	  tbControl =
-	    0 << 26 |  /* post trigger delay 0 */
-		    0x2 << 16 |		/* sequential trace mode */
-	    //	    0x0 << 16 |		/* non-sequential trace mode */
-	    //	    0xf << 4 |		/* watchpoints disabled */
-	    2 << 2 |		/* armed */
-	    2 ;			/* interrupt disabled  */
-	  printk ("setting     tbControl = %08lx\n", tbControl);
-	  write_32bit_cp0_set1_register($22, tbControl);
-	  __asm__ __volatile__(".set noreorder\n\t" \
-			       "nop; nop; nop; nop; nop; nop;\n\t" \
-			       "nop; nop; nop; nop; nop; nop;\n\t" \
-			       ".set reorder\n\t");
-
-	}
-#endif
-}
diff --git a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile
deleted file mode 100644
index c0a0030..0000000
--- a/arch/mips/momentum/ocelot_g/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# Makefile for Momentum Computer's Ocelot-G board.
-#
-
-obj-y	 		+= irq.o gt-irq.o prom.o reset.o setup.o
-obj-$(CONFIG_KGDB)	+= dbg_io.o
diff --git a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c
deleted file mode 100644
index 32d6fb4..0000000
--- a/arch/mips/momentum/ocelot_g/dbg_io.c
+++ /dev/null
@@ -1,121 +0,0 @@
-
-#include <asm/serial.h> /* For the serial port location and base baud */
-
-/* --- CONFIG --- */
-
-typedef unsigned char uint8;
-typedef unsigned int uint32;
-
-/* --- END OF CONFIG --- */
-
-#define         UART16550_BAUD_2400             2400
-#define         UART16550_BAUD_4800             4800
-#define         UART16550_BAUD_9600             9600
-#define         UART16550_BAUD_19200            19200
-#define         UART16550_BAUD_38400            38400
-#define         UART16550_BAUD_57600            57600
-#define         UART16550_BAUD_115200           115200
-
-#define         UART16550_PARITY_NONE           0
-#define         UART16550_PARITY_ODD            0x08
-#define         UART16550_PARITY_EVEN           0x18
-#define         UART16550_PARITY_MARK           0x28
-#define         UART16550_PARITY_SPACE          0x38
-
-#define         UART16550_DATA_5BIT             0x0
-#define         UART16550_DATA_6BIT             0x1
-#define         UART16550_DATA_7BIT             0x2
-#define         UART16550_DATA_8BIT             0x3
-
-#define         UART16550_STOP_1BIT             0x0
-#define         UART16550_STOP_2BIT             0x4
-
-/* ----------------------------------------------------- */
-
-/* === CONFIG === */
-
-/* [jsun] we use the second serial port for kdb */
-#define         BASE                    OCELOT_SERIAL1_BASE
-#define         MAX_BAUD                OCELOT_BASE_BAUD
-
-/* === END OF CONFIG === */
-
-#define         REG_OFFSET              4
-
-/* register offset */
-#define         OFS_RCV_BUFFER          0
-#define         OFS_TRANS_HOLD          0
-#define         OFS_SEND_BUFFER         0
-#define         OFS_INTR_ENABLE         (1*REG_OFFSET)
-#define         OFS_INTR_ID             (2*REG_OFFSET)
-#define         OFS_DATA_FORMAT         (3*REG_OFFSET)
-#define         OFS_LINE_CONTROL        (3*REG_OFFSET)
-#define         OFS_MODEM_CONTROL       (4*REG_OFFSET)
-#define         OFS_RS232_OUTPUT        (4*REG_OFFSET)
-#define         OFS_LINE_STATUS         (5*REG_OFFSET)
-#define         OFS_MODEM_STATUS        (6*REG_OFFSET)
-#define         OFS_RS232_INPUT         (6*REG_OFFSET)
-#define         OFS_SCRATCH_PAD         (7*REG_OFFSET)
-
-#define         OFS_DIVISOR_LSB         (0*REG_OFFSET)
-#define         OFS_DIVISOR_MSB         (1*REG_OFFSET)
-
-
-/* memory-mapped read/write of the port */
-#define         UART16550_READ(y)    (*((volatile uint8*)(BASE + y)))
-#define         UART16550_WRITE(y, z)  ((*((volatile uint8*)(BASE + y))) = z)
-
-void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop)
-{
-	/* disable interrupts */
-	UART16550_WRITE(OFS_INTR_ENABLE, 0);
-
-	/* set up baud rate */
-	{
-		uint32 divisor;
-
-		/* set DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
-
-		/* set divisor */
-		divisor = MAX_BAUD / baud;
-		UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
-		UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
-
-		/* clear DIAB bit */
-		UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
-	}
-
-	/* set data format */
-	UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
-}
-
-static int remoteDebugInitialized = 0;
-
-uint8 getDebugChar(void)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0);
-	return UART16550_READ(OFS_RCV_BUFFER);
-}
-
-
-int putDebugChar(uint8 byte)
-{
-	if (!remoteDebugInitialized) {
-		remoteDebugInitialized = 1;
-		debugInit(UART16550_BAUD_38400,
-			  UART16550_DATA_8BIT,
-			  UART16550_PARITY_NONE, UART16550_STOP_1BIT);
-	}
-
-	while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0);
-	UART16550_WRITE(OFS_SEND_BUFFER, byte);
-	return 1;
-}
diff --git a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c
deleted file mode 100644
index e5576bd..0000000
--- a/arch/mips/momentum/ocelot_g/gt-irq.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- *
- * Copyright 2002 Momentum Computer
- * Author: mdharm@momenco.com
- *
- * arch/mips/momentum/ocelot_g/gt_irq.c
- *     Interrupt routines for gt64240.  Currently it only handles timer irq.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <asm/gt64240.h>
-#include <asm/io.h>
-
-unsigned long bus_clock;
-
-/*
- * These are interrupt handlers for the GT on-chip interrupts.  They
- * all come in to the MIPS on a single interrupt line, and have to
- * be handled and ack'ed differently than other MIPS interrupts.
- */
-
-#if 0
-
-struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH];
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr);
-
-/*
- * Hooks IRQ handler to the system. When the system is interrupted
- * the interrupt service routine is called.
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- * isr_ptr   - Pointer to the interrupt service routine
- */
-void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr)
-{
-	irq_handlers[int_cause][bit_num].routine = isr_ptr;
-}
-
-
-/*
- * Enables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if successful, 0 if failure
- */
-int enable_galileo_irq(int int_cause, int bit_num)
-{
-	if (int_cause == INT_CAUSE_MAIN)
-		SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num));
-	else if (int_cause == INT_CAUSE_HIGH)
-		SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
-			     (1 << bit_num));
-	else
-		return 0;
-
-	return 1;
-}
-
-/*
- * Disables the IRQ on Galileo Chip
- *
- * Inputs :
- * int_cause - The interrupt cause number. In EVB64120 two parameters
- *             are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH.
- * bit_num   - Indicates which bit number in the cause register
- *
- * Outputs :
- * 1 if successful, 0 if failure
- */
-int disable_galileo_irq(int int_cause, int bit_num)
-{
-	if (int_cause == INT_CAUSE_MAIN)
-		RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER,
-			       (1 << bit_num));
-	else if (int_cause == INT_CAUSE_HIGH)
-		RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER,
-			       (1 << bit_num));
-	else
-		return 0;
-	return 1;
-}
-#endif /* 0 */
-
-/*
- * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#.
- *
- * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this
- * routine can handle, for now.
- *
- * In the future, we'll route more interrupts to this pin, and that's why
- * we keep this particular structure in the function.
- */
-
-static irqreturn_t gt64240_p0int_irq(int irq, void *dev)
-{
-	uint32_t irq_src, irq_src_mask;
-	int handled;
-
-	/* get the low interrupt cause register */
-	irq_src = MV_READ(LOW_INTERRUPT_CAUSE_REGISTER);
-
-	/* get the mask register for this pin */
-	irq_src_mask = MV_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW);
-
-	/* mask off only the interrupts we're interested in */
-	irq_src = irq_src & irq_src_mask;
-
-	handled = IRQ_NONE;
-
-	/* Check for timer interrupt */
-	if (irq_src & 0x00000100) {
-		handled = IRQ_HANDLED;
-		irq_src &= ~0x00000100;
-
-		/* Clear any pending cause bits */
-		MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
-
-		/* handle the timer call */
-		do_timer(1);
-#ifndef CONFIG_SMP
-		update_process_times(user_mode(get_irq_regs()));
-#endif
-	}
-
-	if (irq_src) {
-		printk(KERN_INFO
-		       "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n",
-		       irq_src);
-	}
-
-	return handled;
-}
-
-/*
- * Initializes timer using galileo's built in timer.
- */
-
-/*
- * This will ignore the standard MIPS timer interrupt handler
- * that is passed in as *irq (=irq0 in ../kernel/time.c).
- * We will do our own timer interrupt handling.
- */
-void gt64240_time_init(void)
-{
-	static struct irqaction timer;
-
-	/* Stop the timer -- we'll use timer #0 */
-	MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0);
-
-	/* Load timer value for 100 Hz */
-	MV_WRITE(TIMER_COUNTER0, bus_clock / 100);
-
-	/*
-	 * Create the IRQ structure entry for the timer.  Since we're too early
-	 * in the boot process to use the "request_irq()" call, we'll hard-code
-	 * the values to the correct interrupt line.
-	 */
-	timer.handler = &gt64240_p0int_irq;
-	timer.flags = IRQF_SHARED | IRQF_DISABLED;
-	timer.name = "timer";
-	timer.dev_id = NULL;
-	timer.next = NULL;
-	timer.mask = CPU_MASK_NONE;
-	irq_desc[6].action = &timer;
-
-	enable_irq(6);
-
-	/* Clear any pending cause bits */
-	MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0);
-
-	/* Enable the interrupt for timer 0 */
-	MV_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1);
-
-	/* Enable the timer interrupt for GT-64240 pin P0_INT# */
-	MV_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100);
-
-	/* Configure and start the timer */
-	MV_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3);
-}
-
-void gt64240_irq_init(void)
-{
-#if 0
-	int i, j;
-
-	/* Reset irq handlers pointers to NULL */
-	for (i = 0; i < MAX_CAUSE_REGS; i++) {
-		for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) {
-			irq_handlers[i][j].next = NULL;
-			irq_handlers[i][j].sync = 0;
-			irq_handlers[i][j].routine = NULL;
-			irq_handlers[i][j].data = NULL;
-		}
-	}
-#endif /* 0 */
-}
diff --git a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c
deleted file mode 100644
index 273541f..0000000
--- a/arch/mips/momentum/ocelot_g/irq.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2000 RidgeRun, Inc.
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- * Copyright (C) 2000, 01, 05 Ralf Baechle (ralf@linux-mips.org)
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/irq_cpu.h>
-#include <asm/mipsregs.h>
-#include <asm/system.h>
-
-asmlinkage void plat_irq_dispatch(void)
-{
-	unsigned int pending = read_c0_cause() & read_c0_status();
-
-	if (pending & STATUSF_IP2)
-		do_IRQ(2);
-	else if (pending & STATUSF_IP3)
-		do_IRQ(3);
-	else if (pending & STATUSF_IP4)
-		do_IRQ(4);
-	else if (pending & STATUSF_IP5)
-		do_IRQ(5);
-	else if (pending & STATUSF_IP6)
-		do_IRQ(6);
-	else if (pending & STATUSF_IP7)
-		do_IRQ(7);
-	else {
-		/*
-		 * Now look at the extended interrupts
-		 */
-		pending = (read_c0_cause() & (read_c0_intcontrol() << 8)) >> 16;
-
-		if (pending & STATUSF_IP8)
-			do_IRQ(8);
-		else if (pending & STATUSF_IP9)
-			do_IRQ(9);
-		else if (pending & STATUSF_IP10)
-			do_IRQ(10);
-		else if (pending & STATUSF_IP11)
-			do_IRQ(11);
-		else
-			spurious_interrupt();
-	}
-}
-
-extern void gt64240_irq_init(void);
-
-void __init arch_init_irq(void)
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 * int-handler is not on bootstrap
-	 */
-	clear_c0_status(ST0_IM);
-	local_irq_disable();
-
-	mips_cpu_irq_init();
-	rm7k_cpu_irq_init();
-
-	gt64240_irq_init();
-}
diff --git a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h
deleted file mode 100644
index 95e0534..0000000
--- a/arch/mips/momentum/ocelot_g/ocelot_pld.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Ocelot Board Register Definitions
- *
- * (C) 2001 Red Hat, Inc.
- *
- * GPL'd
- */
-#ifndef __MOMENCO_OCELOT_PLD_H__
-#define __MOMENCO_OCELOT_PLD_H__
-
-#define OCELOT_CS0_ADDR (0xfc000000)
-
-#define OCELOT_REG_BOARDREV (0)
-#define OCELOT_REG_PLD1_ID (1)
-#define OCELOT_REG_PLD2_ID (2)
-#define OCELOT_REG_RESET_STATUS (3)
-#define OCELOT_REG_BOARD_STATUS (4)
-#define OCELOT_REG_CPCI_ID (5)
-#define OCELOT_REG_I2C_CTRL (8)
-#define OCELOT_REG_EEPROM_MODE (9)
-#define OCELOT_REG_INTMASK (10)
-#define OCELOT_REG_INTSTATUS (11)
-#define OCELOT_REG_INTSET (12)
-#define OCELOT_REG_INTCLR (13)
-
-#define __PLD_REG_TO_ADDR(reg) ((void *) OCELOT_CS0_ADDR + OCELOT_REG_##reg)
-#define OCELOT_PLD_WRITE(x, reg) writeb(x, __PLD_REG_TO_ADDR(reg))
-#define OCELOT_PLD_READ(reg) readb(__PLD_REG_TO_ADDR(reg))
-
-#endif /* __MOMENCO_OCELOT_PLD_H__ */
diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c
deleted file mode 100644
index 836d08307..0000000
--- a/arch/mips/momentum/ocelot_g/prom.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2002 Momentum Computer Inc.
- * Author: Matthew Dharm <mdharm@momenco.com>
- *
- * Based on Ocelot Linux port, which is
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/bootmem.h>
-
-#include <asm/addrspace.h>
-#include <asm/bootinfo.h>
-#include <asm/pmon.h>
-#include <asm/gt64240.h>
-
-#include "ocelot_pld.h"
-
-struct callvectors* debug_vectors;
-
-extern unsigned long marvell_base;
-extern unsigned long bus_clock;
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
-extern unsigned char prom_mac_addr_base[6];
-#endif
-
-const char *get_system_type(void)
-{
-	return "Momentum Ocelot";
-}
-
-void __init prom_init(void)
-{
-	int argc = fw_arg0;
-	char **arg = (char **) fw_arg1;
-	char **env = (char **) fw_arg2;
-	struct callvectors *cv = (struct callvectors *) fw_arg3;
-	int i;
-
-	/* save the PROM vectors for debugging use */
-	debug_vectors = cv;
-
-	/* arg[0] is "g", the rest is boot parameters */
-	arcs_cmdline[0] = '\0';
-	for (i = 1; i < argc; i++) {
-		if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
-		    >= sizeof(arcs_cmdline))
-			break;
-		strcat(arcs_cmdline, arg[i]);
-		strcat(arcs_cmdline, " ");
-	}
-
-	mips_machgroup = MACH_GROUP_MOMENCO;
-	mips_machtype = MACH_MOMENCO_OCELOT_G;
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
-	/* get the base MAC address for on-board ethernet ports */
-	memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
-#endif
-
-	while (*env) {
-		if (strncmp("gtbase", *env, strlen("gtbase")) == 0) {
-			marvell_base = simple_strtol(*env + strlen("gtbase="),
-							NULL, 16);
-		}
-		if (strncmp("busclock", *env, strlen("busclock")) == 0) {
-			bus_clock = simple_strtol(*env + strlen("busclock="),
-							NULL, 10);
-		}
-		env++;
-	}
-}
-
-void __init prom_free_prom_memory(void)
-{
-}
diff --git a/arch/mips/momentum/ocelot_g/reset.c b/arch/mips/momentum/ocelot_g/reset.c
deleted file mode 100644
index 3fd499a..0000000
--- a/arch/mips/momentum/ocelot_g/reset.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 1997, 2001 Ralf Baechle
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- */
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-#include <linux/delay.h>
-
-void momenco_ocelot_restart(char *command)
-{
-	void *nvram = ioremap_nocache(0x2c807000, 0x1000);
-
-	if (!nvram) {
-		printk(KERN_NOTICE "ioremap of reset register failed\n");
-		return;
-	}
-	writeb(0x84, nvram + 0xff7); /* Ask the NVRAM/RTC/watchdog chip to
-					assert reset in 1/16 second */
-	mdelay(10+(1000/16));
-	iounmap(nvram);
-	printk(KERN_NOTICE "Watchdog reset failed\n");
-}
-
-void momenco_ocelot_halt(void)
-{
-	printk(KERN_NOTICE "\n** You can safely turn off the power\n");
-	while (1)
-		__asm__(".set\tmips3\n\t"
-	                "wait\n\t"
-			".set\tmips0");
-}
-
-void momenco_ocelot_power_off(void)
-{
-	momenco_ocelot_halt();
-}
diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c
deleted file mode 100644
index 9db638a..0000000
--- a/arch/mips/momentum/ocelot_g/setup.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- * Momentum Computer Ocelot-G (CP7000G) - board dependent boot routines
- *
- * Copyright (C) 1996, 1997, 2001  Ralf Baechle
- * Copyright (C) 2000 RidgeRun, Inc.
- * Copyright (C) 2001 Red Hat, Inc.
- * Copyright (C) 2002 Momentum Computer
- *
- * Author: Matthew Dharm, Momentum Computer
- *   mdharm@momenco.com
- *
- * Author: RidgeRun, Inc.
- *   glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com
- *
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/pm.h>
-#include <linux/timex.h>
-#include <linux/vmalloc.h>
-
-#include <asm/time.h>
-#include <asm/bootinfo.h>
-#include <asm/page.h>
-#include <asm/io.h>
-#include <asm/gt64240.h>
-#include <asm/irq.h>
-#include <asm/pci.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <linux/bootmem.h>
-
-#include "ocelot_pld.h"
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
-extern unsigned char prom_mac_addr_base[6];
-#endif
-
-unsigned long marvell_base;
-
-/* These functions are used for rebooting or halting the machine*/
-extern void momenco_ocelot_restart(char *command);
-extern void momenco_ocelot_halt(void);
-extern void momenco_ocelot_power_off(void);
-
-extern void gt64240_time_init(void);
-extern void momenco_ocelot_irq_setup(void);
-
-static char reset_reason;
-
-static unsigned long ENTRYLO(unsigned long paddr)
-{
-	return ((paddr & PAGE_MASK) |
-	       (_PAGE_PRESENT | __READABLE | __WRITEABLE | _PAGE_GLOBAL |
-		_CACHE_UNCACHED)) >> 6;
-}
-
-/* setup code for a handoff from a version 2 PMON 2000 PROM */
-void PMON_v2_setup(void)
-{
-	/* A wired TLB entry for the GT64240 and the serial port. The
-	   GT64240 is going to be hit on every IRQ anyway - there's
-	   absolutely no point in letting it be a random TLB entry, as
-	   it'll just cause needless churning of the TLB. And we use
-	   the other half for the serial port, which is just a PITA
-	   otherwise :)
-
-		Device			Physical	Virtual
-		GT64240 Internal Regs	0xf4000000	0xe0000000
-		UARTs (CS2)		0xfd000000	0xe0001000
-	*/
-	add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000),
-	                0xf4000000, PM_64K);
-	add_wired_entry(ENTRYLO(0xfd000000), ENTRYLO(0xfd001000),
-	                0xfd000000, PM_4K);
-
-	/* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM
-	   in the CS[012] region. We can't use ioremap() yet. The NVRAM
-	   is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions.
-
-		Ocelot PLD (CS0)	0xfc000000	0xe0020000
-		NVRAM (CS1)		0xfc800000	0xe0030000
-	*/
-	add_temporary_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfc010000),
-	                    0xfc000000, PM_64K);
-	add_temporary_entry(ENTRYLO(0xfc800000), ENTRYLO(0xfc810000),
-	                    0xfc800000, PM_64K);
-
-	marvell_base = 0xf4000000;
-}
-
-extern int rm7k_tcache_enabled;
-
-/*
- * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache()
- */
-#define Page_Invalidate_T 0x16
-static void __init setup_l3cache(unsigned long size)
-{
-	int register i;
-
-	printk("Enabling L3 cache...");
-
-	/* Enable the L3 cache in the GT64120A's CPU Configuration register */
-	MV_WRITE(0, MV_READ(0) | (1<<14));
-
-	/* Enable the L3 cache in the CPU */
-	set_c0_config(1<<12 /* CONF_TE */);
-
-	/* Clear the cache */
-	write_c0_taglo(0);
-	write_c0_taghi(0);
-
-	for (i=0; i < size; i+= 4096) {
-		__asm__ __volatile__ (
-			".set noreorder\n\t"
-			".set mips3\n\t"
-			"cache %1, (%0)\n\t"
-			".set mips0\n\t"
-			".set reorder"
-			:
-			: "r" (KSEG0ADDR(i)),
-			  "i" (Page_Invalidate_T));
-	}
-
-	/* Let the RM7000 MM code know that the tertiary cache is enabled */
-	rm7k_tcache_enabled = 1;
-
-	printk("Done\n");
-}
-
-void __init plat_timer_setup(struct irqaction *irq)
-{
-}
-
-void __init plat_mem_setup(void)
-{
-	void (*l3func)(unsigned long) = (void *) KSEG1ADDR(setup_l3cache);
-	unsigned int tmpword;
-
-	board_time_init = gt64240_time_init;
-
-	_machine_restart = momenco_ocelot_restart;
-	_machine_halt = momenco_ocelot_halt;
-	pm_power_off = momenco_ocelot_power_off;
-
-	/*
-	 * initrd_start = (unsigned long)ocelot_initrd_start;
-	 * initrd_end = (unsigned long)ocelot_initrd_start + (ulong)ocelot_initrd_size;
-	 * initrd_below_start_ok = 1;
-	 */
-
-	/* do handoff reconfiguration */
-	PMON_v2_setup();
-
-#ifdef CONFIG_GALILEO_GT64240_ETH
-	/* get the mac addr */
-	memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6);
-#endif
-
-	/* Turn off the Bit-Error LED */
-	OCELOT_PLD_WRITE(0x80, INTCLR);
-
-	tmpword = OCELOT_PLD_READ(BOARDREV);
-	if (tmpword < 26)
-		printk("Momenco Ocelot-G: Board Assembly Rev. %c\n", 'A'+tmpword);
-	else
-		printk("Momenco Ocelot-G: Board Assembly Revision #0x%x\n", tmpword);
-
-	tmpword = OCELOT_PLD_READ(PLD1_ID);
-	printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = OCELOT_PLD_READ(PLD2_ID);
-	printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15);
-	tmpword = OCELOT_PLD_READ(RESET_STATUS);
-	printk("Reset reason: 0x%x\n", tmpword);
-	reset_reason = tmpword;
-	OCELOT_PLD_WRITE(0xff, RESET_STATUS);
-
-	tmpword = OCELOT_PLD_READ(BOARD_STATUS);
-	printk("Board Status register: 0x%02x\n", tmpword);
-	printk("  - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent");
-	printk("  - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent");
-	printk("  - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not");
-	printk("  - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1);
-	printk("  - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3)));
-
-	if (tmpword&12)
-		l3func((1<<(((tmpword&12) >> 2)+20)));
-
-	switch(tmpword &3) {
-	case 3:
-		/* 512MiB -- two banks of 256MiB */
-		add_memory_region(  0x0<<20, 0x100<<20, BOOT_MEM_RAM);
-/*
-		add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM);
-*/
-		break;
-	case 2:
-		/* 256MiB -- two banks of 128MiB */
-		add_memory_region( 0x0<<20, 0x80<<20, BOOT_MEM_RAM);
-		add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM);
-		break;
-	case 1:
-		/* 128MiB -- 64MiB per bank */
-		add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM);
-		add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM);
-		break;
-	case 0:
-		/* 64MiB */
-		add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM);
-		break;
-	}
-
-	/* FIXME: Fix up the DiskOnChip mapping */
-	MV_WRITE(0x468, 0xfef73);
-}
-
-/* This needs to be one of the first initcalls, because no I/O port access
-   can work before this */
-
-static int io_base_ioremap(void)
-{
-	/* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */
-	unsigned long io_remap_range;
-
-	io_remap_range = (unsigned long) ioremap(0xc0000000, 0x30000000);
-	if (!io_remap_range)
-		panic("Could not ioremap I/O port range");
-
-	set_io_port_base(io_remap_range - 0xc0000000);
-
-	return 0;
-}
-
-module_init(io_base_ioremap);
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index df487c0..aba3dbf 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -30,11 +30,9 @@
 obj-$(CONFIG_SOC_AU1550)	+= fixup-au1000.o ops-au1000.o
 obj-$(CONFIG_SOC_PNX8550)	+= fixup-pnx8550.o ops-pnx8550.o
 obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o
-obj-$(CONFIG_MOMENCO_JAGUAR_ATX)+= fixup-jaguar.o
 obj-$(CONFIG_MOMENCO_OCELOT)	+= fixup-ocelot.o pci-ocelot.o
 obj-$(CONFIG_MOMENCO_OCELOT_3)	+= fixup-ocelot3.o
 obj-$(CONFIG_MOMENCO_OCELOT_C)	+= fixup-ocelot-c.o pci-ocelot-c.o
-obj-$(CONFIG_MOMENCO_OCELOT_G)	+= fixup-ocelot-g.o pci-ocelot-g.o
 obj-$(CONFIG_PMC_YOSEMITE)	+= fixup-yosemite.o ops-titan.o ops-titan-ht.o \
 				   pci-yosemite.o
 obj-$(CONFIG_SGI_IP27)		+= ops-bridge.o pci-ip27.o
diff --git a/arch/mips/pci/fixup-cobalt.c b/arch/mips/pci/fixup-cobalt.c
index 7d5f6bb..d57ffd7 100644
--- a/arch/mips/pci/fixup-cobalt.c
+++ b/arch/mips/pci/fixup-cobalt.c
@@ -17,9 +17,7 @@
 #include <asm/io.h>
 #include <asm/gt64120.h>
 
-#include <asm/mach-cobalt/cobalt.h>
-
-extern int cobalt_board_id;
+#include <cobalt.h>
 
 static void qube_raq_galileo_early_fixup(struct pci_dev *dev)
 {
@@ -115,6 +113,27 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_GT64111,
 	 qube_raq_galileo_fixup);
 
+int cobalt_board_id;
+
+static void qube_raq_via_board_id_fixup(struct pci_dev *dev)
+{
+	u8 id;
+	int retval;
+
+	retval = pci_read_config_byte(dev, VIA_COBALT_BRD_ID_REG, &id);
+	if (retval) {
+		panic("Cannot read board ID");
+		return;
+	}
+
+	cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(id);
+
+	printk(KERN_INFO "Cobalt board ID: %d\n", cobalt_board_id);
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0,
+	 qube_raq_via_board_id_fixup);
+
 static char irq_tab_qube1[] __initdata = {
   [COBALT_PCICONF_CPU]     = 0,
   [COBALT_PCICONF_ETH0]    = COBALT_QUBE1_ETH0_IRQ,
diff --git a/arch/mips/pci/fixup-jaguar.c b/arch/mips/pci/fixup-jaguar.c
deleted file mode 100644
index 6c5e1d4..0000000
--- a/arch/mips/pci/fixup-jaguar.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Marvell MV64340 interrupt fixup code.
- *
- * Marvell wants an NDA for their docs so this was written without
- * documentation.  You've been warned.
- *
- * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include <asm/mipsregs.h>
-
-/*
- * WARNING: Example of how _NOT_ to do it.
- */
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int bus = dev->bus->number;
-
-	if (bus == 0 && slot == 1)
-		return 3;	/* PCI-X A */
-	if (bus == 0 && slot == 2)
-		return 4;	/* PCI-X B */
-	if (bus == 1 && slot == 1)
-		return 5;	/* PCI A */
-	if (bus == 1 && slot == 2)
-		return 6;	/* PCI B */
-
-return 0;
-	panic("Whooops in pcibios_map_irq");
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/fixup-ocelot-g.c b/arch/mips/pci/fixup-ocelot-g.c
deleted file mode 100644
index d7a652e..0000000
--- a/arch/mips/pci/fixup-ocelot-g.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
- * Copyright (C) 2004 Ralf Baechle (ralf@linux-mips.org)
- */
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int bus = dev->bus->number;
-
-	if (bus == 0 && slot == 1)	/* Intel 82543 Gigabit MAC */
-		return 2;		/* irq_nr is 2 for INT0 */
-
-	if (bus == 0 && slot == 2)	/* Intel 82543 Gigabit MAC */
-		return 3;		/* irq_nr is 3 for INT1 */
-
-	if (bus == 1 && slot == 3)	/* Intel 21555 bridge */
-		return 5;		/* irq_nr is 8 for INT6 */
-
-	if (bus == 1 && slot == 4)	/* PMC Slot */
-		return 9;		/* irq_nr is 9 for INT7 */
-
-	return -1;
-}
-
-/* Do platform specific device initialization at pci_enable_device() time */
-int pcibios_plat_dev_init(struct pci_dev *dev)
-{
-	return 0;
-}
diff --git a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c
deleted file mode 100644
index 1e34301..0000000
--- a/arch/mips/pci/pci-ocelot-g.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
- *
- * This doesn't really fly - but I don't have a GT64240 system for testing.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <asm/gt64240.h>
-
-/*
- * We assume these address ranges have been programmed into the GT-64240 by
- * the firmware.  PMON in case of the Ocelot G does that.  Note the size of
- * the I/O range is completly stupid; I/O mappings are limited to at most
- * 256 bytes by the PCI spec and deprecated; and just to make things worse
- * apparently many devices don't decode more than 64k of I/O space.
- */
-
-#define gt_io_size	0x20000000UL
-#define gt_io_base	0xe0000000UL
-
-static struct resource gt_pci_mem0_resource = {
-	.name	= "MV64240 PCI0 MEM",
-	.start	= 0xc0000000UL,
-	.end	= 0xcfffffffUL,
-	.flags	= IORESOURCE_MEM
-};
-
-static struct resource gt_pci_io_mem0_resource = {
-	.name	= "MV64240 PCI0 IO MEM",
-	.start	= 0xe0000000UL,
-	.end	= 0xefffffffUL,
-	.flags	= IORESOURCE_IO
-};
-
-static struct mv_pci_controller gt_bus0_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &gt_pci_mem0_resource,
-		.mem_offset	= 0xc0000000UL,
-		.io_resource	= &gt_pci_io_mem0_resource,
-		.io_offset	= 0x00000000UL
-	},
-	.config_addr	= PCI_0CONFIGURATION_ADDRESS,
-	.config_vreg	= PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER,
-};
-
-static struct resource gt_pci_mem1_resource = {
-	.name	= "MV64240 PCI1 MEM",
-	.start	= 0xd0000000UL,
-	.end	= 0xdfffffffUL,
-	.flags	= IORESOURCE_MEM
-};
-
-static struct resource gt_pci_io_mem1_resource = {
-	.name	= "MV64240 PCI1 IO MEM",
-	.start	= 0xf0000000UL,
-	.end	= 0xffffffffUL,
-	.flags	= IORESOURCE_IO
-};
-
-static struct mv_pci_controller gt_bus1_controller = {
-	.pcic = {
-		.pci_ops	= &mv_pci_ops,
-		.mem_resource	= &gt_pci_mem1_resource,
-		.mem_offset	= 0xd0000000UL,
-		.io_resource	= &gt_pci_io_mem1_resource,
-		.io_offset	= 0x10000000UL
-	},
-	.config_addr	= PCI_1CONFIGURATION_ADDRESS,
-	.config_vreg	= PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER,
-};
-
-static __init int __init ocelot_g_pci_init(void)
-{
-	unsigned long io_v_base;
-
-	if (gt_io_size) {
-		io_v_base = (unsigned long) ioremap(gt_io_base, gt_io_size);
-		if (!io_v_base)
-			panic("Could not ioremap I/O port range");
-
-		set_io_port_base(io_v_base);
-	}
-
-	register_pci_controller(&gt_bus0_controller.pcic);
-	register_pci_controller(&gt_bus1_controller.pcic);
-
-	return 0;
-}
-
-arch_initcall(ocelot_g_pci_init);
diff --git a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile
index b6d6492..1fb3e35 100644
--- a/arch/mips/sgi-ip22/Makefile
+++ b/arch/mips/sgi-ip22/Makefile
@@ -4,6 +4,6 @@
 #
 
 obj-y	+= ip22-mc.o ip22-hpc.o ip22-int.o ip22-berr.o \
-	   ip22-time.o ip22-nvram.o ip22-reset.o ip22-setup.o
+	   ip22-time.o ip22-nvram.o ip22-platform.o ip22-reset.o ip22-setup.o
 
 obj-$(CONFIG_EISA)	+= ip22-eisa.o
diff --git a/arch/mips/sgi-ip22/ip22-platform.c b/arch/mips/sgi-ip22/ip22-platform.c
new file mode 100644
index 0000000..78b608d2
--- /dev/null
+++ b/arch/mips/sgi-ip22/ip22-platform.c
@@ -0,0 +1,177 @@
+#include <linux/init.h>
+#include <linux/if_ether.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+
+#include <asm/paccess.h>
+#include <asm/sgi/ip22.h>
+#include <asm/sgi/hpc3.h>
+#include <asm/sgi/mc.h>
+#include <asm/sgi/seeq.h>
+#include <asm/sgi/wd.h>
+
+static struct resource sgiwd93_0_resources[] = {
+	{
+		.name	= "eth0 irq",
+		.start	= SGI_WD93_0_IRQ,
+		.end	= SGI_WD93_0_IRQ,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+static struct sgiwd93_platform_data sgiwd93_0_pd = {
+	.unit	= 0,
+	.irq	= SGI_WD93_0_IRQ,
+};
+
+static struct platform_device sgiwd93_0_device = {
+	.name		= "sgiwd93",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(sgiwd93_0_resources),
+	.resource	= sgiwd93_0_resources,
+	.dev = {
+		.platform_data = &sgiwd93_0_pd,
+	},
+};
+
+static struct resource sgiwd93_1_resources[] = {
+	{
+		.name	= "eth0 irq",
+		.start	= SGI_WD93_1_IRQ,
+		.end	= SGI_WD93_1_IRQ,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+static struct sgiwd93_platform_data sgiwd93_1_pd = {
+	.unit	= 1,
+	.irq	= SGI_WD93_1_IRQ,
+};
+
+static struct platform_device sgiwd93_1_device = {
+	.name		= "sgiwd93",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(sgiwd93_1_resources),
+	.resource	= sgiwd93_1_resources,
+	.dev = {
+		.platform_data = &sgiwd93_1_pd,
+	},
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init sgiwd93_devinit(void)
+{
+	int res;
+
+	sgiwd93_0_pd.hregs	= &hpc3c0->scsi_chan0;
+	sgiwd93_0_pd.wdregs	= (unsigned char *) hpc3c0->scsi0_ext;
+
+	res = platform_device_register(&sgiwd93_0_device);
+	if (res)
+		return res;
+
+	if (!ip22_is_fullhouse())
+		return 0;
+
+	sgiwd93_1_pd.hregs	= &hpc3c0->scsi_chan1;
+	sgiwd93_1_pd.wdregs	= (unsigned char *) hpc3c0->scsi1_ext;
+
+	return platform_device_register(&sgiwd93_1_device);
+}
+
+device_initcall(sgiwd93_devinit);
+
+static struct resource sgiseeq_0_resources[] = {
+	{
+		.name	= "eth0 irq",
+		.start	= SGI_ENET_IRQ,
+		.end	= SGI_ENET_IRQ,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+static struct sgiseeq_platform_data eth0_pd;
+
+static struct platform_device eth0_device = {
+	.name		= "sgiseeq",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(sgiseeq_0_resources),
+	.resource	= sgiseeq_0_resources,
+	.dev = {
+		.platform_data = &eth0_pd,
+	},
+};
+
+static struct resource sgiseeq_1_resources[] = {
+	{
+		.name	= "eth1 irq",
+		.start	= SGI_GIO_0_IRQ,
+		.end	= SGI_GIO_0_IRQ,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+static struct sgiseeq_platform_data eth1_pd;
+
+static struct platform_device eth1_device = {
+	.name		= "sgiseeq",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(sgiseeq_1_resources),
+	.resource	= sgiseeq_1_resources,
+	.dev = {
+		.platform_data = &eth1_pd,
+	},
+};
+
+/*
+ * Create a platform device for the GPI port that receives the
+ * image data from the embedded camera.
+ */
+static int __init sgiseeq_devinit(void)
+{
+	unsigned int tmp;
+	int res, i;
+
+	eth0_pd.hpc = hpc3c0;
+	eth0_pd.irq = SGI_ENET_IRQ;
+#define EADDR_NVOFS     250
+	for (i = 0; i < 3; i++) {
+		unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);
+
+		eth0_pd.mac[2 * i]     = tmp >> 8;
+		eth0_pd.mac[2 * i + 1] = tmp & 0xff;
+	}
+
+	res = platform_device_register(&eth0_device);
+	if (res)
+		return res;
+
+	/* Second HPC is missing? */
+	if (ip22_is_fullhouse() ||
+	    !get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
+		return 0;
+
+	sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 |
+	                 SGIMC_GIOPAR_HPC264;
+	hpc3c1->pbus_piocfg[0][0] = 0x3ffff;
+	/* interrupt/config register on Challenge S Mezz board */
+	hpc3c1->pbus_extregs[0][0] = 0x30;
+
+	eth1_pd.hpc = hpc3c1;
+	eth1_pd.irq = SGI_GIO_0_IRQ;
+#define EADDR_NVOFS     250
+	for (i = 0; i < 3; i++) {
+		unsigned short tmp = ip22_eeprom_read(&hpc3c1->eeprom,
+		                                      EADDR_NVOFS / 2 + i);
+
+		eth1_pd.mac[2 * i]     = tmp >> 8;
+		eth1_pd.mac[2 * i + 1] = tmp & 0xff;
+	}
+
+	return platform_device_register(&eth1_device);
+}
+
+device_initcall(sgiseeq_devinit);
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index 93b7606..112dd51 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -146,7 +146,7 @@
 			interrupt-parent = < &ipic >;
 			interrupts = <42 8>;
 			bus-range = <0 0>;
-			ranges = <02000000 0 a0000000 90000000 0 10000000
+			ranges = <02000000 0 90000000 90000000 0 10000000
 			          42000000 0 80000000 80000000 0 10000000
 			          01000000 0 00000000 d0000000 0 00100000>;
 			clock-frequency = <0>;
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts
index 07bcc51..df773fa 100644
--- a/arch/powerpc/boot/dts/mpc834x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc834x_mds.dts
@@ -223,7 +223,7 @@
 			interrupt-parent = < &ipic >;
 			interrupts = <42 8>;
 			bus-range = <0 0>;
-			ranges = <02000000 0 a0000000 a0000000 0 10000000
+			ranges = <02000000 0 90000000 90000000 0 10000000
 				  42000000 0 80000000 80000000 0 10000000
 				  01000000 0 00000000 e2000000 0 00100000>;
 			clock-frequency = <3f940aa>;
@@ -284,7 +284,7 @@
 			interrupts = <42 8>;
 			bus-range = <0 0>;
 			ranges = <02000000 0 b0000000 b0000000 0 10000000
-				  42000000 0 90000000 90000000 0 10000000
+				  42000000 0 a0000000 a0000000 0 10000000
 				  01000000 0 00000000 e2100000 0 00100000>;
 			clock-frequency = <3f940aa>;
 			#interrupt-cells = <1>;
diff --git a/arch/powerpc/configs/celleb_defconfig b/arch/powerpc/configs/celleb_defconfig
index a1fe971..91b657b 100644
--- a/arch/powerpc/configs/celleb_defconfig
+++ b/arch/powerpc/configs/celleb_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.20-rc4
-# Thu Jan 11 20:55:33 2007
+# Linux kernel version: 2.6.21
+# Tue May  8 12:32:16 2007
 #
 CONFIG_PPC64=y
 CONFIG_64BIT=y
@@ -60,6 +60,7 @@
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_IPC_NS is not set
+CONFIG_SYSVIPC_SYSCTL=y
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
@@ -70,6 +71,7 @@
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
@@ -132,15 +134,26 @@
 # CONFIG_PPC_PSERIES is not set
 # CONFIG_PPC_ISERIES is not set
 # CONFIG_PPC_MPC52xx is not set
+# CONFIG_PPC_MPC5200 is not set
 # CONFIG_PPC_PMAC is not set
 # CONFIG_PPC_MAPLE is not set
 # CONFIG_PPC_PASEMI is not set
+CONFIG_PPC_CELLEB=y
+# CONFIG_PPC_PS3 is not set
 CONFIG_PPC_CELL=y
 # CONFIG_PPC_CELL_NATIVE is not set
 # CONFIG_PPC_IBM_CELL_BLADE is not set
-# CONFIG_PPC_PS3 is not set
-CONFIG_PPC_CELLEB=y
+
+#
+# Cell Broadband Engine options
+#
+CONFIG_SPU_FS=y
+CONFIG_SPU_BASE=y
+# CONFIG_PQ2ADS is not set
 CONFIG_PPC_UDBG_BEAT=y
+# CONFIG_MPIC is not set
+# CONFIG_MPIC_WEIRD is not set
+# CONFIG_PPC_I8259 is not set
 # CONFIG_U3_DART is not set
 # CONFIG_PPC_RTAS is not set
 # CONFIG_MMIO_NVRAM is not set
@@ -149,15 +162,7 @@
 # CONFIG_PPC_INDIRECT_IO is not set
 # CONFIG_GENERIC_IOMAP is not set
 # CONFIG_CPU_FREQ is not set
-# CONFIG_WANT_EARLY_SERIAL is not set
-# CONFIG_MPIC is not set
-
-#
-# Cell Broadband Engine options
-#
-CONFIG_SPU_FS=y
-CONFIG_SPU_BASE=y
-# CONFIG_CBE_RAS is not set
+# CONFIG_CPM2 is not set
 
 #
 # Kernel options
@@ -183,7 +188,6 @@
 CONFIG_NODES_SHIFT=4
 CONFIG_ARCH_SELECT_MEMORY_MODEL=y
 CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_SPARSEMEM_DEFAULT=y
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_SELECT_MEMORY_MODEL=y
 # CONFIG_FLATMEM_MANUAL is not set
@@ -199,6 +203,7 @@
 CONFIG_SPLIT_PTLOCK_CPUS=4
 CONFIG_MIGRATION=y
 CONFIG_RESOURCES_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
 CONFIG_ARCH_MEMORY_PROBE=y
 CONFIG_NODES_SPAN_OTHER_NODES=y
 # CONFIG_PPC_64K_PAGES is not set
@@ -207,14 +212,14 @@
 # CONFIG_CMDLINE_BOOL is not set
 # CONFIG_PM is not set
 CONFIG_SECCOMP=y
+# CONFIG_WANT_DEVICE_TREE is not set
 CONFIG_ISA_DMA_API=y
 
 #
 # Bus options
 #
+CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
-# CONFIG_MPIC_WEIRD is not set
-# CONFIG_PPC_I8259 is not set
 # CONFIG_PPC_INDIRECT_PCI is not set
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
@@ -240,13 +245,13 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
 CONFIG_XFRM=y
 # CONFIG_XFRM_USER is not set
 # CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
@@ -262,7 +267,7 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_TUNNEL=y
 CONFIG_INET_XFRM_MODE_TRANSPORT=y
 CONFIG_INET_XFRM_MODE_TUNNEL=y
 CONFIG_INET_XFRM_MODE_BEET=y
@@ -280,6 +285,7 @@
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 CONFIG_INET6_AH=m
 CONFIG_INET6_ESP=m
 CONFIG_INET6_IPCOMP=m
@@ -302,17 +308,21 @@
 #
 # CONFIG_NETFILTER_NETLINK is not set
 # CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
 # CONFIG_NETFILTER_XTABLES is not set
 
 #
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_QUEUE=m
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
 
 #
 # IPv6: Netfilter Configuration (EXPERIMENTAL)
 #
 # CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
 
 #
 # DCCP Configuration (EXPERIMENTAL)
@@ -352,6 +362,13 @@
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
 # CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
 # CONFIG_IEEE80211 is not set
 
 #
@@ -365,16 +382,13 @@
 CONFIG_PREVENT_FIRMWARE_BUILD=y
 CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
 
 #
 # Connector - unified userspace <-> kernelspace linker
 #
 # CONFIG_CONNECTOR is not set
-
-#
-# Memory Technology Devices (MTD)
-#
 # CONFIG_MTD is not set
 
 #
@@ -385,6 +399,7 @@
 #
 # Plug and Play support
 #
+# CONFIG_PNPACPI is not set
 
 #
 # Block devices
@@ -404,7 +419,6 @@
 CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=131072
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 
@@ -443,7 +457,6 @@
 # CONFIG_BLK_DEV_OPTI621 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
-CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
@@ -458,6 +471,7 @@
 # CONFIG_BLK_DEV_JMICRON is not set
 # CONFIG_BLK_DEV_SC1200 is not set
 # CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
 # CONFIG_BLK_DEV_IT821X is not set
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_PDC202XX_OLD is not set
@@ -468,11 +482,11 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
-CONFIG_BLK_DEV_IDE_CELLEB=y
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_CELLEB=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
-CONFIG_IDEDMA_AUTO=y
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -546,6 +560,7 @@
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_ESP_CORE is not set
 # CONFIG_SCSI_SRP is not set
 
 #
@@ -591,12 +606,7 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-
-#
-# Macintosh device drivers
-#
-# CONFIG_MAC_EMUMOUSEBTN is not set
-# CONFIG_WINDFARM is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
 
 #
 # Network device support
@@ -652,15 +662,18 @@
 # CONFIG_BNX2 is not set
 CONFIG_SPIDER_NET=y
 # CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
 # CONFIG_IXGB is not set
 # CONFIG_S2IO is not set
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
+# CONFIG_PASEMI_MAC is not set
 
 #
 # Token Ring devices
@@ -668,9 +681,10 @@
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Wireless LAN
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
 
 #
 # Wan interfaces
@@ -770,6 +784,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_TXX9=y
 CONFIG_HAS_TXX9_SERIAL=y
+CONFIG_SERIAL_TXX9_NR_UARTS=3
 CONFIG_SERIAL_TXX9_CONSOLE=y
 # CONFIG_SERIAL_TXX9_STDSERIAL is not set
 # CONFIG_SERIAL_JSM is not set
@@ -891,6 +906,11 @@
 # CONFIG_HWMON_VID is not set
 
 #
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+
+#
 # Multimedia devices
 #
 # CONFIG_VIDEO_DEV is not set
@@ -904,7 +924,7 @@
 #
 # Graphics support
 #
-# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 # CONFIG_FB is not set
 # CONFIG_FB_IBM_GXT4500 is not set
 
@@ -913,7 +933,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -924,6 +943,15 @@
 # HID Devices
 #
 CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+CONFIG_USB_HIDDEV=y
 
 #
 # USB support
@@ -938,9 +966,8 @@
 # Miscellaneous USB options
 #
 CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_BANDWIDTH is not set
+# CONFIG_USB_DEVICE_CLASS is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_MULTITHREAD_PROBE is not set
 # CONFIG_USB_OTG is not set
 
 #
@@ -953,6 +980,7 @@
 CONFIG_USB_EHCI_BIG_ENDIAN_MMIO=y
 # CONFIG_USB_ISP116X_HCD is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_HCD_PPC_OF is not set
 # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
 CONFIG_USB_OHCI_BIG_ENDIAN_MMIO=y
 CONFIG_USB_OHCI_LITTLE_ENDIAN=y
@@ -989,10 +1017,6 @@
 #
 # USB Input Devices
 #
-CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
-CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_ACECAD is not set
@@ -1005,6 +1029,7 @@
 # CONFIG_USB_ATI_REMOTE2 is not set
 # CONFIG_USB_KEYSPAN_REMOTE is not set
 # CONFIG_USB_APPLETOUCH is not set
+# CONFIG_USB_GTCO is not set
 
 #
 # USB Imaging devices
@@ -1042,6 +1067,7 @@
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYPRESS_CY7C63 is not set
 # CONFIG_USB_CYTHERM is not set
@@ -1052,6 +1078,7 @@
 # CONFIG_USB_SISUSBVGA is not set
 # CONFIG_USB_LD is not set
 # CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 
 #
@@ -1109,6 +1136,10 @@
 #
 
 #
+# Auxiliary Display support
+#
+
+#
 # Virtualization
 #
 
@@ -1293,6 +1324,8 @@
 # Distributed Lock Manager
 #
 # CONFIG_DLM is not set
+# CONFIG_UCC_SLOW is not set
+# CONFIG_UCC_FAST is not set
 
 #
 # Library routines
@@ -1305,7 +1338,8 @@
 CONFIG_ZLIB_INFLATE=m
 CONFIG_ZLIB_DEFLATE=m
 CONFIG_PLIST=y
-CONFIG_IOMAP_COPY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
 
 #
 # Instrumentation Support
@@ -1323,15 +1357,16 @@
 CONFIG_DEBUG_FS=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
 CONFIG_LOG_BUF_SHIFT=15
 CONFIG_DETECT_SOFTLOCKUP=y
 # CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_RT_MUTEXES is not set
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_RWSEMS is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
 # CONFIG_DEBUG_KOBJECT is not set
@@ -1341,8 +1376,10 @@
 # CONFIG_DEBUG_LIST is not set
 # CONFIG_FORCED_INLINING is not set
 # CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
 # CONFIG_DEBUG_STACKOVERFLOW is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
@@ -1356,6 +1393,7 @@
 # CONFIG_PPC_EARLY_DEBUG_RTAS_CONSOLE is not set
 # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set
 # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set
+# CONFIG_PPC_EARLY_DEBUG_PAS_REALMODE is not set
 CONFIG_PPC_EARLY_DEBUG_BEAT=y
 
 #
@@ -1385,8 +1423,10 @@
 # CONFIG_CRYPTO_GF128MUL is not set
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
 CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_TWOFISH_COMMON=m
@@ -1401,6 +1441,7 @@
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
+# CONFIG_CRYPTO_CAMELLIA is not set
 CONFIG_CRYPTO_TEST=m
 
 #
diff --git a/arch/powerpc/kernel/audit.c b/arch/powerpc/kernel/audit.c
index 7fe5e63..a4dab7c 100644
--- a/arch/powerpc/kernel/audit.c
+++ b/arch/powerpc/kernel/audit.c
@@ -23,6 +23,20 @@
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_PPC64
+	if (arch == AUDIT_ARCH_PPC)
+		return 1;
+#endif
+	return 0;
+}
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_PPC64
@@ -51,15 +65,18 @@
 	extern __u32 ppc32_write_class[];
 	extern __u32 ppc32_read_class[];
 	extern __u32 ppc32_chattr_class[];
+	extern __u32 ppc32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, ppc32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, ppc32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ppc32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ppc32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, ppc32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
diff --git a/arch/powerpc/kernel/compat_audit.c b/arch/powerpc/kernel/compat_audit.c
index 640d4bb..108ff14 100644
--- a/arch/powerpc/kernel/compat_audit.c
+++ b/arch/powerpc/kernel/compat_audit.c
@@ -21,6 +21,11 @@
 ~0U
 };
 
+unsigned ppc32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int ppc32_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 9ed4931..068377a 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -173,7 +173,7 @@
 		lv1_get_version_info(&tmp);
 	}
 
-	hard_irq_enable();
+	__hard_irq_enable();
 }
 #endif /* CONFIG_PPC64 */
 
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 6d05a1f..b0409e1 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -1098,35 +1098,24 @@
 				unsigned long *start_virt, unsigned long *size)
 {
 	struct pci_controller *hose = pci_bus_to_host(bus);
-	struct pci_bus_region region;
 	struct resource *res;
 
-	if (bus->self) {
+	if (bus->self)
 		res = bus->resource[0];
-		pcibios_resource_to_bus(bus->self, &region, res);
-		*start_phys = hose->io_base_phys + region.start;
-		*start_virt = (unsigned long) hose->io_base_virt + 
-				region.start;
-		if (region.end > region.start) 
-			*size = region.end - region.start + 1;
-		else {
-			printk("%s(): unexpected region 0x%lx->0x%lx\n", 
-					__FUNCTION__, region.start, region.end);
-			return 1;
-		}
-		
-	} else {
+	else
 		/* Root Bus */
 		res = &hose->io_resource;
-		*start_phys = hose->io_base_phys + res->start;
-		*start_virt = (unsigned long) hose->io_base_virt + res->start;
-		if (res->end > res->start)
-			*size = res->end - res->start + 1;
-		else {
-			printk("%s(): unexpected region 0x%lx->0x%lx\n", 
-					__FUNCTION__, res->start, res->end);
-			return 1;
-		}
+
+	*start_virt = pci_io_base + res->start;
+	*start_phys = *start_virt + hose->io_base_phys
+		- (unsigned long) hose->io_base_virt;
+
+	if (res->end > res->start)
+		*size = res->end - res->start + 1;
+	else {
+		printk("%s(): unexpected region 0x%lx->0x%lx\n",
+		       __FUNCTION__, res->start, res->end);
+		return 1;
 	}
 
 	return 0;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index caef555..c065b55 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -716,11 +716,40 @@
 	return 0;
 }
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static void __init early_init_dt_check_for_initrd(unsigned long node)
+{
+	unsigned long l;
+	u32 *prop;
+
+	DBG("Looking for initrd properties... ");
+
+	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
+	if (prop) {
+		initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
+
+		prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
+		if (prop) {
+			initrd_end = (unsigned long)
+					__va(of_read_ulong(prop, l/4));
+			initrd_below_start_ok = 1;
+		} else {
+			initrd_start = 0;
+		}
+	}
+
+	DBG("initrd_start=0x%lx  initrd_end=0x%lx\n", initrd_start, initrd_end);
+}
+#else
+static inline void early_init_dt_check_for_initrd(unsigned long node)
+{
+}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 static int __init early_init_dt_scan_chosen(unsigned long node,
 					    const char *uname, int depth, void *data)
 {
 	unsigned long *lprop;
-	u32 *prop;
 	unsigned long l;
 	char *p;
 
@@ -762,21 +791,7 @@
                crashk_res.end = crashk_res.start + *lprop - 1;
 #endif
 
-#ifdef CONFIG_BLK_DEV_INITRD
-	DBG("Looking for initrd properties... ");
-	prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
-	if (prop) {
-		initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
-		prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
-		if (prop) {
-			initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4));
-			initrd_below_start_ok = 1;
-		} else {
-			initrd_start = 0;
-		}
-	}
-	DBG("initrd_start=0x%lx  initrd_end=0x%lx\n", initrd_start, initrd_end);
-#endif /* CONFIG_BLK_DEV_INITRD */
+	early_init_dt_check_for_initrd(node);
 
 	/* Retreive command line */
  	p = of_get_flat_dt_prop(node, "bootargs", &l);
diff --git a/arch/powerpc/kernel/swsusp.c b/arch/powerpc/kernel/swsusp.c
index 064a7ba..77b7b34 100644
--- a/arch/powerpc/kernel/swsusp.c
+++ b/arch/powerpc/kernel/swsusp.c
@@ -36,8 +36,4 @@
 #ifdef CONFIG_PPC32
 	set_context(current->active_mm->context.id, current->active_mm->pgd);
 #endif
-
-#ifdef CONFIG_PPC64
-	hard_irq_enable();
-#endif
 }
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 450258d..0a486d4 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -23,7 +23,5 @@
 endif
 
 # Temporary hack until we have migrated to asm-powerpc
-ifeq ($(CONFIG_PPC_MERGE),y)
 obj-$(CONFIG_8xx)	+= rheap.o
 obj-$(CONFIG_CPM2)	+= rheap.o
-endif
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 6c5c5dd..b2f6dcc 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -133,7 +133,7 @@
 	info->empty_slots--;
 
 	/* Initialize */
-	blk->start = NULL;
+	blk->start = 0;
 	blk->size = 0;
 	blk->owner = NULL;
 
@@ -158,7 +158,7 @@
 
 	/* We assume that they are aligned properly */
 	size = blkn->size;
-	s = (unsigned long)blkn->start;
+	s = blkn->start;
 	e = s + size;
 
 	/* Find the blocks immediately before and after the given one
@@ -170,7 +170,7 @@
 	list_for_each(l, &info->free_list) {
 		blk = list_entry(l, rh_block_t, list);
 
-		bs = (unsigned long)blk->start;
+		bs = blk->start;
 		be = bs + blk->size;
 
 		if (next == NULL && s >= bs)
@@ -188,10 +188,10 @@
 	}
 
 	/* Now check if they are really adjacent */
-	if (before != NULL && s != (unsigned long)before->start + before->size)
+	if (before && s != (before->start + before->size))
 		before = NULL;
 
-	if (after != NULL && e != (unsigned long)after->start)
+	if (after && e != after->start)
 		after = NULL;
 
 	/* No coalescing; list insert and return */
@@ -216,7 +216,7 @@
 
 	/* Grow the after block backwards */
 	if (before == NULL && after != NULL) {
-		after->start = (int8_t *)after->start - size;
+		after->start -= size;
 		after->size += size;
 		return;
 	}
@@ -321,14 +321,14 @@
 }
 
 /* Attach a free memory region, coalesces regions if adjuscent */
-int rh_attach_region(rh_info_t * info, void *start, int size)
+int rh_attach_region(rh_info_t * info, unsigned long start, int size)
 {
 	rh_block_t *blk;
 	unsigned long s, e, m;
 	int r;
 
 	/* The region must be aligned */
-	s = (unsigned long)start;
+	s = start;
 	e = s + size;
 	m = info->alignment - 1;
 
@@ -338,9 +338,12 @@
 	/* Round end down */
 	e = e & ~m;
 
+	if (IS_ERR_VALUE(e) || (e < s))
+		return -ERANGE;
+
 	/* Take final values */
-	start = (void *)s;
-	size = (int)(e - s);
+	start = s;
+	size = e - s;
 
 	/* Grow the blocks, if needed */
 	r = assure_empty(info, 1);
@@ -358,7 +361,7 @@
 }
 
 /* Detatch given address range, splits free block if needed. */
-void *rh_detach_region(rh_info_t * info, void *start, int size)
+unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size)
 {
 	struct list_head *l;
 	rh_block_t *blk, *newblk;
@@ -366,10 +369,10 @@
 
 	/* Validate size */
 	if (size <= 0)
-		return ERR_PTR(-EINVAL);
+		return (unsigned long) -EINVAL;
 
 	/* The region must be aligned */
-	s = (unsigned long)start;
+	s = start;
 	e = s + size;
 	m = info->alignment - 1;
 
@@ -380,34 +383,34 @@
 	e = e & ~m;
 
 	if (assure_empty(info, 1) < 0)
-		return ERR_PTR(-ENOMEM);
+		return (unsigned long) -ENOMEM;
 
 	blk = NULL;
 	list_for_each(l, &info->free_list) {
 		blk = list_entry(l, rh_block_t, list);
 		/* The range must lie entirely inside one free block */
-		bs = (unsigned long)blk->start;
-		be = (unsigned long)blk->start + blk->size;
+		bs = blk->start;
+		be = blk->start + blk->size;
 		if (s >= bs && e <= be)
 			break;
 		blk = NULL;
 	}
 
 	if (blk == NULL)
-		return ERR_PTR(-ENOMEM);
+		return (unsigned long) -ENOMEM;
 
 	/* Perfect fit */
 	if (bs == s && be == e) {
 		/* Delete from free list, release slot */
 		list_del(&blk->list);
 		release_slot(info, blk);
-		return (void *)s;
+		return s;
 	}
 
 	/* blk still in free list, with updated start and/or size */
 	if (bs == s || be == e) {
 		if (bs == s)
-			blk->start = (int8_t *)blk->start + size;
+			blk->start += size;
 		blk->size -= size;
 
 	} else {
@@ -416,25 +419,29 @@
 
 		/* the back free fragment */
 		newblk = get_slot(info);
-		newblk->start = (void *)e;
+		newblk->start = e;
 		newblk->size = be - e;
 
 		list_add(&newblk->list, &blk->list);
 	}
 
-	return (void *)s;
+	return s;
 }
 
-void *rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
+/* Allocate a block of memory at the specified alignment.  The value returned
+ * is an offset into the buffer initialized by rh_init(), or a negative number
+ * if there is an error.
+ */
+unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment, const char *owner)
 {
 	struct list_head *l;
 	rh_block_t *blk;
 	rh_block_t *newblk;
-	void *start;
+	unsigned long start;
 
-	/* Validate size, (must be power of two) */
+	/* Validate size, and alignment must be power of two */
 	if (size <= 0 || (alignment & (alignment - 1)) != 0)
-		return ERR_PTR(-EINVAL);
+		return (unsigned long) -EINVAL;
 
 	/* given alignment larger that default rheap alignment */
 	if (alignment > info->alignment)
@@ -444,7 +451,7 @@
 	size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
 
 	if (assure_empty(info, 1) < 0)
-		return ERR_PTR(-ENOMEM);
+		return (unsigned long) -ENOMEM;
 
 	blk = NULL;
 	list_for_each(l, &info->free_list) {
@@ -455,7 +462,7 @@
 	}
 
 	if (blk == NULL)
-		return ERR_PTR(-ENOMEM);
+		return (unsigned long) -ENOMEM;
 
 	/* Just fits */
 	if (blk->size == size) {
@@ -475,7 +482,7 @@
 	newblk->owner = owner;
 
 	/* blk still in free list, with updated start, size */
-	blk->start = (int8_t *)blk->start + size;
+	blk->start += size;
 	blk->size -= size;
 
 	start = newblk->start;
@@ -486,19 +493,25 @@
 	/* this is no problem with the deallocator since */
 	/* we scan for pointers that lie in the blocks   */
 	if (alignment > info->alignment)
-		start = (void *)(((unsigned long)start + alignment - 1) &
-				~(alignment - 1));
+		start = (start + alignment - 1) & ~(alignment - 1);
 
 	return start;
 }
 
-void *rh_alloc(rh_info_t * info, int size, const char *owner)
+/* Allocate a block of memory at the default alignment.  The value returned is
+ * an offset into the buffer initialized by rh_init(), or a negative number if
+ * there is an error.
+ */
+unsigned long rh_alloc(rh_info_t * info, int size, const char *owner)
 {
 	return rh_alloc_align(info, size, info->alignment, owner);
 }
 
-/* allocate at precisely the given address */
-void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
+/* Allocate a block of memory at the given offset, rounded up to the default
+ * alignment.  The value returned is an offset into the buffer initialized by
+ * rh_init(), or a negative number if there is an error.
+ */
+unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, const char *owner)
 {
 	struct list_head *l;
 	rh_block_t *blk, *newblk1, *newblk2;
@@ -506,10 +519,10 @@
 
 	/* Validate size */
 	if (size <= 0)
-		return ERR_PTR(-EINVAL);
+		return (unsigned long) -EINVAL;
 
 	/* The region must be aligned */
-	s = (unsigned long)start;
+	s = start;
 	e = s + size;
 	m = info->alignment - 1;
 
@@ -520,20 +533,20 @@
 	e = e & ~m;
 
 	if (assure_empty(info, 2) < 0)
-		return ERR_PTR(-ENOMEM);
+		return (unsigned long) -ENOMEM;
 
 	blk = NULL;
 	list_for_each(l, &info->free_list) {
 		blk = list_entry(l, rh_block_t, list);
 		/* The range must lie entirely inside one free block */
-		bs = (unsigned long)blk->start;
-		be = (unsigned long)blk->start + blk->size;
+		bs = blk->start;
+		be = blk->start + blk->size;
 		if (s >= bs && e <= be)
 			break;
 	}
 
 	if (blk == NULL)
-		return ERR_PTR(-ENOMEM);
+		return (unsigned long) -ENOMEM;
 
 	/* Perfect fit */
 	if (bs == s && be == e) {
@@ -551,7 +564,7 @@
 	/* blk still in free list, with updated start and/or size */
 	if (bs == s || be == e) {
 		if (bs == s)
-			blk->start = (int8_t *)blk->start + size;
+			blk->start += size;
 		blk->size -= size;
 
 	} else {
@@ -560,14 +573,14 @@
 
 		/* The back free fragment */
 		newblk2 = get_slot(info);
-		newblk2->start = (void *)e;
+		newblk2->start = e;
 		newblk2->size = be - e;
 
 		list_add(&newblk2->list, &blk->list);
 	}
 
 	newblk1 = get_slot(info);
-	newblk1->start = (void *)s;
+	newblk1->start = s;
 	newblk1->size = e - s;
 	newblk1->owner = owner;
 
@@ -577,7 +590,11 @@
 	return start;
 }
 
-int rh_free(rh_info_t * info, void *start)
+/* Deallocate the memory previously allocated by one of the rh_alloc functions.
+ * The return value is the size of the deallocated block, or a negative number
+ * if there is an error.
+ */
+int rh_free(rh_info_t * info, unsigned long start)
 {
 	rh_block_t *blk, *blk2;
 	struct list_head *l;
@@ -642,7 +659,7 @@
 	return nr;
 }
 
-int rh_set_owner(rh_info_t * info, void *start, const char *owner)
+int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner)
 {
 	rh_block_t *blk, *blk2;
 	struct list_head *l;
@@ -684,8 +701,8 @@
 		nr = maxnr;
 	for (i = 0; i < nr; i++)
 		printk(KERN_INFO
-		       "    0x%p-0x%p (%u)\n",
-		       st[i].start, (int8_t *) st[i].start + st[i].size,
+		       "    0x%lx-0x%lx (%u)\n",
+		       st[i].start, st[i].start + st[i].size,
 		       st[i].size);
 	printk(KERN_INFO "\n");
 
@@ -695,8 +712,8 @@
 		nr = maxnr;
 	for (i = 0; i < nr; i++)
 		printk(KERN_INFO
-		       "    0x%p-0x%p (%u) %s\n",
-		       st[i].start, (int8_t *) st[i].start + st[i].size,
+		       "    0x%lx-0x%lx (%u) %s\n",
+		       st[i].start, st[i].start + st[i].size,
 		       st[i].size, st[i].owner != NULL ? st[i].owner : "");
 	printk(KERN_INFO "\n");
 }
@@ -704,6 +721,6 @@
 void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
 {
 	printk(KERN_INFO
-	       "blk @0x%p: 0x%p-0x%p (%u)\n",
-	       blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
+	       "blk @0x%p: 0x%lx-0x%lx (%u)\n",
+	       blk, blk->start, blk->start + blk->size, blk->size);
 }
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c
index 7b7fe2d..7d722ee 100644
--- a/arch/powerpc/mm/hash_native_64.c
+++ b/arch/powerpc/mm/hash_native_64.c
@@ -376,31 +376,28 @@
 		}
 	}
 
-	/*
-	 * FIXME, the code below works for 16M, 64K, and 4K pages as these
-	 * fall under the p<=23 rules for calculating the virtual address.
-	 * In the case of 16M pages, an extra bit is stolen from the AVPN
-	 * field to achieve the requisite 24 bits.
-	 *
-	 * Does not work for 16G pages or 1 TB segments.
-	 */
+	/* This works for all page sizes, and for 256M and 1T segments */
 	shift = mmu_psize_defs[size].shift;
-	if (mmu_psize_defs[size].avpnm)
-		avpnm_bits = __ilog2_u64(mmu_psize_defs[size].avpnm) + 1;
-	else
-		avpnm_bits = 0;
-	if (shift - avpnm_bits <= 23) {
-		avpn = HPTE_V_AVPN_VAL(hpte_v) << 23;
+	avpn = (HPTE_V_AVPN_VAL(hpte_v) & ~mmu_psize_defs[size].avpnm) << 23;
 
-		if (shift < 23) {
-			unsigned long vpi, pteg;
+	if (shift < 23) {
+		unsigned long vpi, vsid, pteg;
 
-			pteg = slot / HPTES_PER_GROUP;
-			if (hpte_v & HPTE_V_SECONDARY)
-				pteg = ~pteg;
+		pteg = slot / HPTES_PER_GROUP;
+		if (hpte_v & HPTE_V_SECONDARY)
+			pteg = ~pteg;
+		switch (hpte_v >> HPTE_V_SSIZE_SHIFT) {
+		case MMU_SEGSIZE_256M:
 			vpi = ((avpn >> 28) ^ pteg) & htab_hash_mask;
-			avpn |= (vpi << mmu_psize_defs[size].shift);
+			break;
+		case MMU_SEGSIZE_1T:
+			vsid = avpn >> 40;
+			vpi = (vsid ^ (vsid << 25) ^ pteg) & htab_hash_mask;
+			break;
+		default:
+			avpn = vpi = psize = 0;
 		}
+		avpn |= (vpi << mmu_psize_defs[size].shift);
 	}
 
 	*va = avpn;
diff --git a/arch/powerpc/platforms/83xx/mpc8313_rdb.c b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
index 32e9e94..96970ac 100644
--- a/arch/powerpc/platforms/83xx/mpc8313_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc8313_rdb.c
@@ -40,7 +40,9 @@
  */
 static void __init mpc8313_rdb_setup_arch(void)
 {
+#ifdef CONFIG_PCI
 	struct device_node *np;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc8313_rdb_setup_arch()", 0);
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
index b0b22bb..3db68b7 100644
--- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c
+++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c
@@ -44,7 +44,9 @@
  */
 static void __init mpc832x_rdb_setup_arch(void)
 {
+#if defined(CONFIG_PCI) || defined(CONFIG_QUICC_ENGINE)
 	struct device_node *np;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc832x_rdb_setup_arch()", 0);
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index 3c009f6..40a0194 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -50,7 +50,9 @@
  */
 static void __init mpc834x_itx_setup_arch(void)
 {
+#ifdef CONFIG_PCI
 	struct device_node *np;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_itx_setup_arch()", 0);
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c
index 8aa9a93..10394b2 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_mds.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c
@@ -120,7 +120,9 @@
  */
 static void __init mpc834x_mds_setup_arch(void)
 {
+#ifdef CONFIG_PCI
 	struct device_node *np;
+#endif
 
 	if (ppc_md.progress)
 		ppc_md.progress("mpc834x_mds_setup_arch()", 0);
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 90877565..1051702 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -168,7 +168,7 @@
 {
 	unsigned short temp;
 	struct pci_controller *hose = pci_bus_to_host(dev->bus);
-	unsigned char irq2pin[16];
+	unsigned char irq2pin[16], c;
 	unsigned long pirq_map_word = 0;
 	u32 irq;
 	int i;
@@ -288,6 +288,11 @@
 	outb(0x1e, 0x4d1);
 
 #undef ULI1575_SET_DEV_IRQ
+
+	/* Disable the HD interface and enable the AC97 interface. */
+	pci_read_config_byte(dev, 0xb8, &c);
+	c &= 0x7f;
+	pci_write_config_byte(dev, 0xb8, c);
 }
 
 static void __devinit quirk_uli5288(struct pci_dev *dev)
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 8c20f0f..812bf56 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -43,12 +43,10 @@
 	unsigned long ctrl, thread_switch_control;
 
 	/*
-	 * We need to hard disable interrupts, but we also need to mark them
-	 * hard disabled in the PACA so that the local_irq_enable() done by
-	 * our caller upon return propertly hard enables.
+	 * We need to hard disable interrupts, the local_irq_enable() done by
+	 * our caller upon return will hard re-enable.
 	 */
 	hard_irq_disable();
-	get_paca()->hard_enabled = 0;
 
 	ctrl = mfspr(SPRN_CTRLF);
 
diff --git a/arch/powerpc/platforms/celleb/pci.c b/arch/powerpc/platforms/celleb/pci.c
index d1adf34..e9ac19c 100644
--- a/arch/powerpc/platforms/celleb/pci.c
+++ b/arch/powerpc/platforms/celleb/pci.c
@@ -457,6 +457,7 @@
 
 	pr_debug("PCI: celleb_setup_phb() %s\n", name);
 	phb_set_bus_ranges(dev, phb);
+	phb->buid = 1;
 
 	if (strcmp(name, "epci") == 0) {
 		phb->ops = &celleb_epci_ops;
diff --git a/arch/powerpc/platforms/celleb/scc_epci.c b/arch/powerpc/platforms/celleb/scc_epci.c
index fb23d53..c4b0110 100644
--- a/arch/powerpc/platforms/celleb/scc_epci.c
+++ b/arch/powerpc/platforms/celleb/scc_epci.c
@@ -133,13 +133,13 @@
 }
 
 static volatile void __iomem *celleb_epci_make_config_addr(
+					struct pci_bus *bus,
 					struct pci_controller *hose,
 					unsigned int devfn, int where)
 {
 	volatile void __iomem *addr;
-	struct pci_bus *bus = hose->bus;
 
-	if (bus->self)
+	if (bus != hose->bus)
 		addr = celleb_epci_get_epci_cfg(hose) +
 		       (((bus->number & 0xff) << 16)
 		        | ((devfn & 0xff) << 8)
@@ -193,7 +193,7 @@
 	} else {
 
 		clear_and_disable_master_abort_interrupt(hose);
-		addr = celleb_epci_make_config_addr(hose, devfn, where);
+		addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
 
 		switch (size) {
 		case 1:
@@ -257,7 +257,7 @@
 	} else {
 
 		clear_and_disable_master_abort_interrupt(hose);
-		addr = celleb_epci_make_config_addr(hose, devfn, where);
+		addr = celleb_epci_make_config_addr(bus, hose, devfn, where);
 
 		switch (size) {
 		case 1:
diff --git a/arch/powerpc/platforms/celleb/setup.c b/arch/powerpc/platforms/celleb/setup.c
index 596ab2a..5e9f7f1 100644
--- a/arch/powerpc/platforms/celleb/setup.c
+++ b/arch/powerpc/platforms/celleb/setup.c
@@ -80,7 +80,7 @@
 	return 0;
 }
 
-__setup("celleb_machine_type_hack", celleb_machine_type_hack);
+__setup("celleb_machine_type_hack=", celleb_machine_type_hack);
 
 static void celleb_progress(char *s, unsigned short hex)
 {
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 093438b..5f3e6d8 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -76,7 +76,7 @@
  */
 #define EEH_MAX_FAILS	2100000
 
-/* Time to wait for a PCI slot to retport status, in milliseconds */
+/* Time to wait for a PCI slot to report status, in milliseconds */
 #define PCI_BUS_RESET_WAIT_MSEC (60*1000)
 
 /* RTAS tokens */
@@ -95,11 +95,18 @@
 /* Lock to avoid races due to multiple reports of an error */
 static DEFINE_SPINLOCK(confirm_error_lock);
 
-/* Buffer for reporting slot-error-detail rtas calls */
+/* Buffer for reporting slot-error-detail rtas calls. Its here
+ * in BSS, and not dynamically alloced, so that it ends up in
+ * RMO where RTAS can access it.
+ */
 static unsigned char slot_errbuf[RTAS_ERROR_LOG_MAX];
 static DEFINE_SPINLOCK(slot_errbuf_lock);
 static int eeh_error_buf_size;
 
+/* Buffer for reporting pci register dumps. Its here in BSS, and
+ * not dynamically alloced, so that it ends up in RMO where RTAS
+ * can access it.
+ */
 #define EEH_PCI_REGS_LOG_LEN 4096
 static unsigned char pci_regs_buf[EEH_PCI_REGS_LOG_LEN];
 
@@ -218,7 +225,7 @@
 void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
 {
 	size_t loglen = 0;
-	memset(pci_regs_buf, 0, EEH_PCI_REGS_LOG_LEN);
+	pci_regs_buf[0] = 0;
 
 	rtas_pci_enable(pdn, EEH_THAW_MMIO);
 	loglen = gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c
index f07d849..161a584 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -378,8 +378,9 @@
 
 	/* Since rtas may enable MMIO when posting the error log,
 	 * don't post the error log until after all dev drivers
-	 * have been informed. */
-	eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */);
+	 * have been informed.
+	 */
+	eeh_slot_error_detail(frozen_pdn, EEH_LOG_TEMP_FAILURE);
 
 	/* If all device drivers were EEH-unaware, then shut
 	 * down all of the device drivers, and hope they
@@ -470,7 +471,7 @@
 		location, drv_str, pci_str);
 
 perm_error:
-	eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */);
+	eeh_slot_error_detail(frozen_pdn, EEH_LOG_PERM_FAILURE);
 
 	/* Notify all devices that they're about to go down. */
 	pci_walk_bus(frozen_bus, eeh_report_failure, NULL);
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index eec684a..be17d23 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -520,7 +520,6 @@
 		dev->dev.archdata.dma_data = PCI_DN(pdn)->iommu_table;
 		return;
 	}
-	DBG("  found DMA window, table: %p\n", pci->iommu_table);
 
 	pci = PCI_DN(pdn);
 	if (!pci->iommu_table) {
@@ -534,6 +533,8 @@
 
 		pci->iommu_table = iommu_init_table(tbl, pci->phb->node);
 		DBG("  created table: %p\n", pci->iommu_table);
+	} else {
+		DBG("  found DMA window, table: %p\n", pci->iommu_table);
 	}
 
 	dev->dev.archdata.dma_data = pci->iommu_table;
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c
index af26856..412a5e7 100644
--- a/arch/powerpc/platforms/pseries/kexec.c
+++ b/arch/powerpc/platforms/pseries/kexec.c
@@ -12,6 +12,7 @@
 #include <asm/firmware.h>
 #include <asm/kexec.h>
 #include <asm/mpic.h>
+#include <asm/smp.h>
 
 #include "pseries.h"
 #include "xics.h"
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index 9b4fafd..4f67b89 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -330,7 +330,7 @@
 	 * with the processor and the microcode patches applied / activated.
 	 * But the following should be at least safe.
 	 */
-	rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+	rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
 }
 
 /*
@@ -338,9 +338,9 @@
  * This function returns an offset into the DPRAM area.
  * Use cpm_dpram_addr() to get the virtual address of the area.
  */
-uint cpm_dpalloc(uint size, uint align)
+unsigned long cpm_dpalloc(uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
@@ -352,30 +352,30 @@
 }
 EXPORT_SYMBOL(cpm_dpalloc);
 
-int cpm_dpfree(uint offset)
+int cpm_dpfree(unsigned long offset)
 {
 	int ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
-	ret = rh_free(&cpm_dpmem_info, (void *)offset);
+	ret = rh_free(&cpm_dpmem_info, offset);
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
 	return ret;
 }
 EXPORT_SYMBOL(cpm_dpfree);
 
-uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
 	cpm_dpmem_info.alignment = align;
-	start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+	start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
-	return (uint)start;
+	return start;
 }
 EXPORT_SYMBOL(cpm_dpalloc_fixed);
 
@@ -385,7 +385,7 @@
 }
 EXPORT_SYMBOL(cpm_dpdump);
 
-void *cpm_dpram_addr(uint offset)
+void *cpm_dpram_addr(unsigned long offset)
 {
 	return (void *)(dpram_vbase + offset);
 }
diff --git a/arch/powerpc/sysdev/cpm2_common.c b/arch/powerpc/sysdev/cpm2_common.c
index ec26599..9244129 100644
--- a/arch/powerpc/sysdev/cpm2_common.c
+++ b/arch/powerpc/sysdev/cpm2_common.c
@@ -248,15 +248,14 @@
 	 * varies with the processor and the microcode patches activated.
 	 * But the following should be at least safe.
 	 */
-	rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE,
-			CPM_DATAONLY_SIZE);
+	rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
 }
 
 /* This function returns an index into the DPRAM area.
  */
-uint cpm_dpalloc(uint size, uint align)
+unsigned long cpm_dpalloc(uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
@@ -268,13 +267,13 @@
 }
 EXPORT_SYMBOL(cpm_dpalloc);
 
-int cpm_dpfree(uint offset)
+int cpm_dpfree(unsigned long offset)
 {
 	int ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
-	ret = rh_free(&cpm_dpmem_info, (void *)offset);
+	ret = rh_free(&cpm_dpmem_info, offset);
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
 	return ret;
@@ -282,17 +281,17 @@
 EXPORT_SYMBOL(cpm_dpfree);
 
 /* not sure if this is ever needed */
-uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
 	cpm_dpmem_info.alignment = align;
-	start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+	start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
-	return (uint)start;
+	return start;
 }
 EXPORT_SYMBOL(cpm_dpalloc_fixed);
 
@@ -302,7 +301,7 @@
 }
 EXPORT_SYMBOL(cpm_dpdump);
 
-void *cpm_dpram_addr(uint offset)
+void *cpm_dpram_addr(unsigned long offset)
 {
 	return (void *)(im_dprambase + offset);
 }
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c
index 7f4c075..90f8740 100644
--- a/arch/powerpc/sysdev/qe_lib/qe.c
+++ b/arch/powerpc/sysdev/qe_lib/qe.c
@@ -244,7 +244,7 @@
 static int qe_sdma_init(void)
 {
 	struct sdma *sdma = &qe_immr->sdma;
-	u32 sdma_buf_offset;
+	unsigned long sdma_buf_offset;
 
 	if (!sdma)
 		return -ENODEV;
@@ -252,10 +252,10 @@
 	/* allocate 2 internal temporary buffers (512 bytes size each) for
 	 * the SDMA */
  	sdma_buf_offset = qe_muram_alloc(512 * 2, 4096);
-	if (IS_MURAM_ERR(sdma_buf_offset))
+	if (IS_ERR_VALUE(sdma_buf_offset))
 		return -ENOMEM;
 
-	out_be32(&sdma->sdebcr, sdma_buf_offset & QE_SDEBCR_BA_MASK);
+	out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
  	out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
  					(0x1 << QE_SDMR_CEN_SHIFT)));
 
@@ -291,33 +291,32 @@
 	if ((np = of_find_node_by_name(NULL, "data-only")) != NULL) {
 		address = *of_get_address(np, 0, &size, &flags);
 		of_node_put(np);
-		rh_attach_region(&qe_muram_info,
-			(void *)address, (int)size);
+		rh_attach_region(&qe_muram_info, address, (int) size);
 	}
 }
 
 /* This function returns an index into the MURAM area.
  */
-u32 qe_muram_alloc(u32 size, u32 align)
+unsigned long qe_muram_alloc(int size, int align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&qe_muram_lock, flags);
 	start = rh_alloc_align(&qe_muram_info, size, align, "QE");
 	spin_unlock_irqrestore(&qe_muram_lock, flags);
 
-	return (u32) start;
+	return start;
 }
 EXPORT_SYMBOL(qe_muram_alloc);
 
-int qe_muram_free(u32 offset)
+int qe_muram_free(unsigned long offset)
 {
 	int ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&qe_muram_lock, flags);
-	ret = rh_free(&qe_muram_info, (void *)offset);
+	ret = rh_free(&qe_muram_info, offset);
 	spin_unlock_irqrestore(&qe_muram_lock, flags);
 
 	return ret;
@@ -325,16 +324,16 @@
 EXPORT_SYMBOL(qe_muram_free);
 
 /* not sure if this is ever needed */
-u32 qe_muram_alloc_fixed(u32 offset, u32 size)
+unsigned long qe_muram_alloc_fixed(unsigned long offset, int size)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&qe_muram_lock, flags);
-	start = rh_alloc_fixed(&qe_muram_info, (void *)offset, size, "commproc");
+	start = rh_alloc_fixed(&qe_muram_info, offset, size, "commproc");
 	spin_unlock_irqrestore(&qe_muram_lock, flags);
 
-	return (u32) start;
+	return start;
 }
 EXPORT_SYMBOL(qe_muram_alloc_fixed);
 
@@ -344,7 +343,7 @@
 }
 EXPORT_SYMBOL(qe_muram_dump);
 
-void *qe_muram_addr(u32 offset)
+void *qe_muram_addr(unsigned long offset)
 {
 	return (void *)&qe_immr->muram[offset];
 }
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index 66137bf..9143236 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
@@ -268,7 +269,7 @@
 	/* Allocate memory for Tx Virtual Fifo */
 	uccf->ucc_fast_tx_virtual_fifo_base_offset =
 	    qe_muram_alloc(uf_info->utfs, UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
-	if (IS_MURAM_ERR(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
+	if (IS_ERR_VALUE(uccf->ucc_fast_tx_virtual_fifo_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate MURAM for TX FIFO", __FUNCTION__);
 		uccf->ucc_fast_tx_virtual_fifo_base_offset = 0;
 		ucc_fast_free(uccf);
@@ -280,7 +281,7 @@
 		qe_muram_alloc(uf_info->urfs +
 			   UCC_FAST_RECEIVE_VIRTUAL_FIFO_SIZE_FUDGE_FACTOR,
 			   UCC_FAST_VIRT_FIFO_REGS_ALIGNMENT);
-	if (IS_MURAM_ERR(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
+	if (IS_ERR_VALUE(uccf->ucc_fast_rx_virtual_fifo_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate MURAM for RX FIFO", __FUNCTION__);
 		uccf->ucc_fast_rx_virtual_fifo_base_offset = 0;
 		ucc_fast_free(uccf);
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index b930d68..1f65c26 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/stddef.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
 
 #include <asm/io.h>
 #include <asm/immap_qe.h>
@@ -175,7 +176,7 @@
 	/* Get PRAM base */
 	uccs->us_pram_offset =
 		qe_muram_alloc(UCC_SLOW_PRAM_SIZE, ALIGNMENT_OF_UCC_SLOW_PRAM);
-	if (IS_MURAM_ERR(uccs->us_pram_offset)) {
+	if (IS_ERR_VALUE(uccs->us_pram_offset)) {
 		printk(KERN_ERR "%s: cannot allocate MURAM for PRAM", __FUNCTION__);
 		ucc_slow_free(uccs);
 		return -ENOMEM;
@@ -210,7 +211,7 @@
 	uccs->rx_base_offset =
 		qe_muram_alloc(us_info->rx_bd_ring_len * sizeof(struct qe_bd),
 				QE_ALIGNMENT_OF_BD);
-	if (IS_MURAM_ERR(uccs->rx_base_offset)) {
+	if (IS_ERR_VALUE(uccs->rx_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate RX BDs", __FUNCTION__);
 		uccs->rx_base_offset = 0;
 		ucc_slow_free(uccs);
@@ -220,7 +221,7 @@
 	uccs->tx_base_offset =
 		qe_muram_alloc(us_info->tx_bd_ring_len * sizeof(struct qe_bd),
 			QE_ALIGNMENT_OF_BD);
-	if (IS_MURAM_ERR(uccs->tx_base_offset)) {
+	if (IS_ERR_VALUE(uccs->tx_base_offset)) {
 		printk(KERN_ERR "%s: cannot allocate TX BDs", __FUNCTION__);
 		uccs->tx_base_offset = 0;
 		ucc_slow_free(uccs);
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 7a8722b..e2c6210 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -402,7 +402,7 @@
 	 * with the processor and the microcode patches applied / activated.
 	 * But the following should be at least safe.
 	 */
-	rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
+	rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
 }
 
 /*
@@ -410,9 +410,9 @@
  * This function returns an offset into the DPRAM area.
  * Use cpm_dpram_addr() to get the virtual address of the area.
  */
-uint cpm_dpalloc(uint size, uint align)
+unsigned long cpm_dpalloc(uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
@@ -420,34 +420,34 @@
 	start = rh_alloc(&cpm_dpmem_info, size, "commproc");
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
-	return (uint)start;
+	return start;
 }
 EXPORT_SYMBOL(cpm_dpalloc);
 
-int cpm_dpfree(uint offset)
+int cpm_dpfree(unsigned long offset)
 {
 	int ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
-	ret = rh_free(&cpm_dpmem_info, (void *)offset);
+	ret = rh_free(&cpm_dpmem_info, offset);
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
 	return ret;
 }
 EXPORT_SYMBOL(cpm_dpfree);
 
-uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
 	cpm_dpmem_info.alignment = align;
-	start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+	start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
-	return (uint)start;
+	return start;
 }
 EXPORT_SYMBOL(cpm_dpalloc_fixed);
 
@@ -457,7 +457,7 @@
 }
 EXPORT_SYMBOL(cpm_dpdump);
 
-void *cpm_dpram_addr(uint offset)
+void *cpm_dpram_addr(unsigned long offset)
 {
 	return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset;
 }
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
index 422bef9..095e661 100644
--- a/arch/ppc/lib/Makefile
+++ b/arch/ppc/lib/Makefile
@@ -3,6 +3,3 @@
 #
 
 obj-y			:= checksum.o string.o div64.o
-
-obj-$(CONFIG_8xx)	+= rheap.o
-obj-$(CONFIG_CPM2)	+= rheap.o
diff --git a/arch/ppc/lib/rheap.c b/arch/ppc/lib/rheap.c
deleted file mode 100644
index d407007..0000000
--- a/arch/ppc/lib/rheap.c
+++ /dev/null
@@ -1,692 +0,0 @@
-/*
- * A Remote Heap.  Remote means that we don't touch the memory that the
- * heap points to. Normal heap implementations use the memory they manage
- * to place their list. We cannot do that because the memory we manage may
- * have special properties, for example it is uncachable or of different
- * endianess.
- *
- * Author: Pantelis Antoniou <panto@intracom.gr>
- *
- * 2004 (c) INTRACOM S.A. Greece. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include <asm/rheap.h>
-
-/*
- * Fixup a list_head, needed when copying lists.  If the pointers fall
- * between s and e, apply the delta.  This assumes that
- * sizeof(struct list_head *) == sizeof(unsigned long *).
- */
-static inline void fixup(unsigned long s, unsigned long e, int d,
-			 struct list_head *l)
-{
-	unsigned long *pp;
-
-	pp = (unsigned long *)&l->next;
-	if (*pp >= s && *pp < e)
-		*pp += d;
-
-	pp = (unsigned long *)&l->prev;
-	if (*pp >= s && *pp < e)
-		*pp += d;
-}
-
-/* Grow the allocated blocks */
-static int grow(rh_info_t * info, int max_blocks)
-{
-	rh_block_t *block, *blk;
-	int i, new_blocks;
-	int delta;
-	unsigned long blks, blke;
-
-	if (max_blocks <= info->max_blocks)
-		return -EINVAL;
-
-	new_blocks = max_blocks - info->max_blocks;
-
-	block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_KERNEL);
-	if (block == NULL)
-		return -ENOMEM;
-
-	if (info->max_blocks > 0) {
-
-		/* copy old block area */
-		memcpy(block, info->block,
-		       sizeof(rh_block_t) * info->max_blocks);
-
-		delta = (char *)block - (char *)info->block;
-
-		/* and fixup list pointers */
-		blks = (unsigned long)info->block;
-		blke = (unsigned long)(info->block + info->max_blocks);
-
-		for (i = 0, blk = block; i < info->max_blocks; i++, blk++)
-			fixup(blks, blke, delta, &blk->list);
-
-		fixup(blks, blke, delta, &info->empty_list);
-		fixup(blks, blke, delta, &info->free_list);
-		fixup(blks, blke, delta, &info->taken_list);
-
-		/* free the old allocated memory */
-		if ((info->flags & RHIF_STATIC_BLOCK) == 0)
-			kfree(info->block);
-	}
-
-	info->block = block;
-	info->empty_slots += new_blocks;
-	info->max_blocks = max_blocks;
-	info->flags &= ~RHIF_STATIC_BLOCK;
-
-	/* add all new blocks to the free list */
-	for (i = 0, blk = block + info->max_blocks; i < new_blocks; i++, blk++)
-		list_add(&blk->list, &info->empty_list);
-
-	return 0;
-}
-
-/*
- * Assure at least the required amount of empty slots.  If this function
- * causes a grow in the block area then all pointers kept to the block
- * area are invalid!
- */
-static int assure_empty(rh_info_t * info, int slots)
-{
-	int max_blocks;
-
-	/* This function is not meant to be used to grow uncontrollably */
-	if (slots >= 4)
-		return -EINVAL;
-
-	/* Enough space */
-	if (info->empty_slots >= slots)
-		return 0;
-
-	/* Next 16 sized block */
-	max_blocks = ((info->max_blocks + slots) + 15) & ~15;
-
-	return grow(info, max_blocks);
-}
-
-static rh_block_t *get_slot(rh_info_t * info)
-{
-	rh_block_t *blk;
-
-	/* If no more free slots, and failure to extend. */
-	/* XXX: You should have called assure_empty before */
-	if (info->empty_slots == 0) {
-		printk(KERN_ERR "rh: out of slots; crash is imminent.\n");
-		return NULL;
-	}
-
-	/* Get empty slot to use */
-	blk = list_entry(info->empty_list.next, rh_block_t, list);
-	list_del_init(&blk->list);
-	info->empty_slots--;
-
-	/* Initialize */
-	blk->start = NULL;
-	blk->size = 0;
-	blk->owner = NULL;
-
-	return blk;
-}
-
-static inline void release_slot(rh_info_t * info, rh_block_t * blk)
-{
-	list_add(&blk->list, &info->empty_list);
-	info->empty_slots++;
-}
-
-static void attach_free_block(rh_info_t * info, rh_block_t * blkn)
-{
-	rh_block_t *blk;
-	rh_block_t *before;
-	rh_block_t *after;
-	rh_block_t *next;
-	int size;
-	unsigned long s, e, bs, be;
-	struct list_head *l;
-
-	/* We assume that they are aligned properly */
-	size = blkn->size;
-	s = (unsigned long)blkn->start;
-	e = s + size;
-
-	/* Find the blocks immediately before and after the given one
-	 * (if any) */
-	before = NULL;
-	after = NULL;
-	next = NULL;
-
-	list_for_each(l, &info->free_list) {
-		blk = list_entry(l, rh_block_t, list);
-
-		bs = (unsigned long)blk->start;
-		be = bs + blk->size;
-
-		if (next == NULL && s >= bs)
-			next = blk;
-
-		if (be == s)
-			before = blk;
-
-		if (e == bs)
-			after = blk;
-
-		/* If both are not null, break now */
-		if (before != NULL && after != NULL)
-			break;
-	}
-
-	/* Now check if they are really adjacent */
-	if (before != NULL && s != (unsigned long)before->start + before->size)
-		before = NULL;
-
-	if (after != NULL && e != (unsigned long)after->start)
-		after = NULL;
-
-	/* No coalescing; list insert and return */
-	if (before == NULL && after == NULL) {
-
-		if (next != NULL)
-			list_add(&blkn->list, &next->list);
-		else
-			list_add(&blkn->list, &info->free_list);
-
-		return;
-	}
-
-	/* We don't need it anymore */
-	release_slot(info, blkn);
-
-	/* Grow the before block */
-	if (before != NULL && after == NULL) {
-		before->size += size;
-		return;
-	}
-
-	/* Grow the after block backwards */
-	if (before == NULL && after != NULL) {
-		after->start = (int8_t *)after->start - size;
-		after->size += size;
-		return;
-	}
-
-	/* Grow the before block, and release the after block */
-	before->size += size + after->size;
-	list_del(&after->list);
-	release_slot(info, after);
-}
-
-static void attach_taken_block(rh_info_t * info, rh_block_t * blkn)
-{
-	rh_block_t *blk;
-	struct list_head *l;
-
-	/* Find the block immediately before the given one (if any) */
-	list_for_each(l, &info->taken_list) {
-		blk = list_entry(l, rh_block_t, list);
-		if (blk->start > blkn->start) {
-			list_add_tail(&blkn->list, &blk->list);
-			return;
-		}
-	}
-
-	list_add_tail(&blkn->list, &info->taken_list);
-}
-
-/*
- * Create a remote heap dynamically.  Note that no memory for the blocks
- * are allocated.  It will upon the first allocation
- */
-rh_info_t *rh_create(unsigned int alignment)
-{
-	rh_info_t *info;
-
-	/* Alignment must be a power of two */
-	if ((alignment & (alignment - 1)) != 0)
-		return ERR_PTR(-EINVAL);
-
-	info = kmalloc(sizeof(*info), GFP_KERNEL);
-	if (info == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	info->alignment = alignment;
-
-	/* Initially everything as empty */
-	info->block = NULL;
-	info->max_blocks = 0;
-	info->empty_slots = 0;
-	info->flags = 0;
-
-	INIT_LIST_HEAD(&info->empty_list);
-	INIT_LIST_HEAD(&info->free_list);
-	INIT_LIST_HEAD(&info->taken_list);
-
-	return info;
-}
-
-/*
- * Destroy a dynamically created remote heap.  Deallocate only if the areas
- * are not static
- */
-void rh_destroy(rh_info_t * info)
-{
-	if ((info->flags & RHIF_STATIC_BLOCK) == 0 && info->block != NULL)
-		kfree(info->block);
-
-	if ((info->flags & RHIF_STATIC_INFO) == 0)
-		kfree(info);
-}
-
-/*
- * Initialize in place a remote heap info block.  This is needed to support
- * operation very early in the startup of the kernel, when it is not yet safe
- * to call kmalloc.
- */
-void rh_init(rh_info_t * info, unsigned int alignment, int max_blocks,
-	     rh_block_t * block)
-{
-	int i;
-	rh_block_t *blk;
-
-	/* Alignment must be a power of two */
-	if ((alignment & (alignment - 1)) != 0)
-		return;
-
-	info->alignment = alignment;
-
-	/* Initially everything as empty */
-	info->block = block;
-	info->max_blocks = max_blocks;
-	info->empty_slots = max_blocks;
-	info->flags = RHIF_STATIC_INFO | RHIF_STATIC_BLOCK;
-
-	INIT_LIST_HEAD(&info->empty_list);
-	INIT_LIST_HEAD(&info->free_list);
-	INIT_LIST_HEAD(&info->taken_list);
-
-	/* Add all new blocks to the free list */
-	for (i = 0, blk = block; i < max_blocks; i++, blk++)
-		list_add(&blk->list, &info->empty_list);
-}
-
-/* Attach a free memory region, coalesces regions if adjuscent */
-int rh_attach_region(rh_info_t * info, void *start, int size)
-{
-	rh_block_t *blk;
-	unsigned long s, e, m;
-	int r;
-
-	/* The region must be aligned */
-	s = (unsigned long)start;
-	e = s + size;
-	m = info->alignment - 1;
-
-	/* Round start up */
-	s = (s + m) & ~m;
-
-	/* Round end down */
-	e = e & ~m;
-
-	/* Take final values */
-	start = (void *)s;
-	size = (int)(e - s);
-
-	/* Grow the blocks, if needed */
-	r = assure_empty(info, 1);
-	if (r < 0)
-		return r;
-
-	blk = get_slot(info);
-	blk->start = start;
-	blk->size = size;
-	blk->owner = NULL;
-
-	attach_free_block(info, blk);
-
-	return 0;
-}
-
-/* Detatch given address range, splits free block if needed. */
-void *rh_detach_region(rh_info_t * info, void *start, int size)
-{
-	struct list_head *l;
-	rh_block_t *blk, *newblk;
-	unsigned long s, e, m, bs, be;
-
-	/* Validate size */
-	if (size <= 0)
-		return ERR_PTR(-EINVAL);
-
-	/* The region must be aligned */
-	s = (unsigned long)start;
-	e = s + size;
-	m = info->alignment - 1;
-
-	/* Round start up */
-	s = (s + m) & ~m;
-
-	/* Round end down */
-	e = e & ~m;
-
-	if (assure_empty(info, 1) < 0)
-		return ERR_PTR(-ENOMEM);
-
-	blk = NULL;
-	list_for_each(l, &info->free_list) {
-		blk = list_entry(l, rh_block_t, list);
-		/* The range must lie entirely inside one free block */
-		bs = (unsigned long)blk->start;
-		be = (unsigned long)blk->start + blk->size;
-		if (s >= bs && e <= be)
-			break;
-		blk = NULL;
-	}
-
-	if (blk == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	/* Perfect fit */
-	if (bs == s && be == e) {
-		/* Delete from free list, release slot */
-		list_del(&blk->list);
-		release_slot(info, blk);
-		return (void *)s;
-	}
-
-	/* blk still in free list, with updated start and/or size */
-	if (bs == s || be == e) {
-		if (bs == s)
-			blk->start = (int8_t *)blk->start + size;
-		blk->size -= size;
-
-	} else {
-		/* The front free fragment */
-		blk->size = s - bs;
-
-		/* the back free fragment */
-		newblk = get_slot(info);
-		newblk->start = (void *)e;
-		newblk->size = be - e;
-
-		list_add(&newblk->list, &blk->list);
-	}
-
-	return (void *)s;
-}
-
-void *rh_alloc(rh_info_t * info, int size, const char *owner)
-{
-	struct list_head *l;
-	rh_block_t *blk;
-	rh_block_t *newblk;
-	void *start;
-
-	/* Validate size */
-	if (size <= 0)
-		return ERR_PTR(-EINVAL);
-
-	/* Align to configured alignment */
-	size = (size + (info->alignment - 1)) & ~(info->alignment - 1);
-
-	if (assure_empty(info, 1) < 0)
-		return ERR_PTR(-ENOMEM);
-
-	blk = NULL;
-	list_for_each(l, &info->free_list) {
-		blk = list_entry(l, rh_block_t, list);
-		if (size <= blk->size)
-			break;
-		blk = NULL;
-	}
-
-	if (blk == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	/* Just fits */
-	if (blk->size == size) {
-		/* Move from free list to taken list */
-		list_del(&blk->list);
-		blk->owner = owner;
-		start = blk->start;
-
-		attach_taken_block(info, blk);
-
-		return start;
-	}
-
-	newblk = get_slot(info);
-	newblk->start = blk->start;
-	newblk->size = size;
-	newblk->owner = owner;
-
-	/* blk still in free list, with updated start, size */
-	blk->start = (int8_t *)blk->start + size;
-	blk->size -= size;
-
-	start = newblk->start;
-
-	attach_taken_block(info, newblk);
-
-	return start;
-}
-
-/* allocate at precisely the given address */
-void *rh_alloc_fixed(rh_info_t * info, void *start, int size, const char *owner)
-{
-	struct list_head *l;
-	rh_block_t *blk, *newblk1, *newblk2;
-	unsigned long s, e, m, bs, be;
-
-	/* Validate size */
-	if (size <= 0)
-		return ERR_PTR(-EINVAL);
-
-	/* The region must be aligned */
-	s = (unsigned long)start;
-	e = s + size;
-	m = info->alignment - 1;
-
-	/* Round start up */
-	s = (s + m) & ~m;
-
-	/* Round end down */
-	e = e & ~m;
-
-	if (assure_empty(info, 2) < 0)
-		return ERR_PTR(-ENOMEM);
-
-	blk = NULL;
-	list_for_each(l, &info->free_list) {
-		blk = list_entry(l, rh_block_t, list);
-		/* The range must lie entirely inside one free block */
-		bs = (unsigned long)blk->start;
-		be = (unsigned long)blk->start + blk->size;
-		if (s >= bs && e <= be)
-			break;
-	}
-
-	if (blk == NULL)
-		return ERR_PTR(-ENOMEM);
-
-	/* Perfect fit */
-	if (bs == s && be == e) {
-		/* Move from free list to taken list */
-		list_del(&blk->list);
-		blk->owner = owner;
-
-		start = blk->start;
-		attach_taken_block(info, blk);
-
-		return start;
-
-	}
-
-	/* blk still in free list, with updated start and/or size */
-	if (bs == s || be == e) {
-		if (bs == s)
-			blk->start = (int8_t *)blk->start + size;
-		blk->size -= size;
-
-	} else {
-		/* The front free fragment */
-		blk->size = s - bs;
-
-		/* The back free fragment */
-		newblk2 = get_slot(info);
-		newblk2->start = (void *)e;
-		newblk2->size = be - e;
-
-		list_add(&newblk2->list, &blk->list);
-	}
-
-	newblk1 = get_slot(info);
-	newblk1->start = (void *)s;
-	newblk1->size = e - s;
-	newblk1->owner = owner;
-
-	start = newblk1->start;
-	attach_taken_block(info, newblk1);
-
-	return start;
-}
-
-int rh_free(rh_info_t * info, void *start)
-{
-	rh_block_t *blk, *blk2;
-	struct list_head *l;
-	int size;
-
-	/* Linear search for block */
-	blk = NULL;
-	list_for_each(l, &info->taken_list) {
-		blk2 = list_entry(l, rh_block_t, list);
-		if (start < blk2->start)
-			break;
-		blk = blk2;
-	}
-
-	if (blk == NULL || start > (blk->start + blk->size))
-		return -EINVAL;
-
-	/* Remove from taken list */
-	list_del(&blk->list);
-
-	/* Get size of freed block */
-	size = blk->size;
-	attach_free_block(info, blk);
-
-	return size;
-}
-
-int rh_get_stats(rh_info_t * info, int what, int max_stats, rh_stats_t * stats)
-{
-	rh_block_t *blk;
-	struct list_head *l;
-	struct list_head *h;
-	int nr;
-
-	switch (what) {
-
-	case RHGS_FREE:
-		h = &info->free_list;
-		break;
-
-	case RHGS_TAKEN:
-		h = &info->taken_list;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Linear search for block */
-	nr = 0;
-	list_for_each(l, h) {
-		blk = list_entry(l, rh_block_t, list);
-		if (stats != NULL && nr < max_stats) {
-			stats->start = blk->start;
-			stats->size = blk->size;
-			stats->owner = blk->owner;
-			stats++;
-		}
-		nr++;
-	}
-
-	return nr;
-}
-
-int rh_set_owner(rh_info_t * info, void *start, const char *owner)
-{
-	rh_block_t *blk, *blk2;
-	struct list_head *l;
-	int size;
-
-	/* Linear search for block */
-	blk = NULL;
-	list_for_each(l, &info->taken_list) {
-		blk2 = list_entry(l, rh_block_t, list);
-		if (start < blk2->start)
-			break;
-		blk = blk2;
-	}
-
-	if (blk == NULL || start > (blk->start + blk->size))
-		return -EINVAL;
-
-	blk->owner = owner;
-	size = blk->size;
-
-	return size;
-}
-
-void rh_dump(rh_info_t * info)
-{
-	static rh_stats_t st[32];	/* XXX maximum 32 blocks */
-	int maxnr;
-	int i, nr;
-
-	maxnr = ARRAY_SIZE(st);
-
-	printk(KERN_INFO
-	       "info @0x%p (%d slots empty / %d max)\n",
-	       info, info->empty_slots, info->max_blocks);
-
-	printk(KERN_INFO "  Free:\n");
-	nr = rh_get_stats(info, RHGS_FREE, maxnr, st);
-	if (nr > maxnr)
-		nr = maxnr;
-	for (i = 0; i < nr; i++)
-		printk(KERN_INFO
-		       "    0x%p-0x%p (%u)\n",
-		       st[i].start, (int8_t *) st[i].start + st[i].size,
-		       st[i].size);
-	printk(KERN_INFO "\n");
-
-	printk(KERN_INFO "  Taken:\n");
-	nr = rh_get_stats(info, RHGS_TAKEN, maxnr, st);
-	if (nr > maxnr)
-		nr = maxnr;
-	for (i = 0; i < nr; i++)
-		printk(KERN_INFO
-		       "    0x%p-0x%p (%u) %s\n",
-		       st[i].start, (int8_t *) st[i].start + st[i].size,
-		       st[i].size, st[i].owner != NULL ? st[i].owner : "");
-	printk(KERN_INFO "\n");
-}
-
-void rh_dump_blk(rh_info_t * info, rh_block_t * blk)
-{
-	printk(KERN_INFO
-	       "blk @0x%p: 0x%p-0x%p (%u)\n",
-	       blk, blk->start, (int8_t *) blk->start + blk->size, blk->size);
-}
diff --git a/arch/ppc/syslib/cpm2_common.c b/arch/ppc/syslib/cpm2_common.c
index cbac44b..6cd859d 100644
--- a/arch/ppc/syslib/cpm2_common.c
+++ b/arch/ppc/syslib/cpm2_common.c
@@ -136,15 +136,14 @@
 	 * varies with the processor and the microcode patches activated.
 	 * But the following should be at least safe.
 	 */
-	rh_attach_region(&cpm_dpmem_info, (void *)CPM_DATAONLY_BASE,
-			CPM_DATAONLY_SIZE);
+	rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
 }
 
 /* This function returns an index into the DPRAM area.
  */
-uint cpm_dpalloc(uint size, uint align)
+unsigned long cpm_dpalloc(uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
@@ -152,17 +151,17 @@
 	start = rh_alloc(&cpm_dpmem_info, size, "commproc");
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
-	return (uint)start;
+	return start;
 }
 EXPORT_SYMBOL(cpm_dpalloc);
 
-int cpm_dpfree(uint offset)
+int cpm_dpfree(unsigned long offset)
 {
 	int ret;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
-	ret = rh_free(&cpm_dpmem_info, (void *)offset);
+	ret = rh_free(&cpm_dpmem_info, offset);
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
 	return ret;
@@ -170,17 +169,17 @@
 EXPORT_SYMBOL(cpm_dpfree);
 
 /* not sure if this is ever needed */
-uint cpm_dpalloc_fixed(uint offset, uint size, uint align)
+unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
 {
-	void *start;
+	unsigned long start;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cpm_dpmem_lock, flags);
 	cpm_dpmem_info.alignment = align;
-	start = rh_alloc_fixed(&cpm_dpmem_info, (void *)offset, size, "commproc");
+	start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
 	spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
 
-	return (uint)start;
+	return start;
 }
 EXPORT_SYMBOL(cpm_dpalloc_fixed);
 
@@ -190,7 +189,7 @@
 }
 EXPORT_SYMBOL(cpm_dpdump);
 
-void *cpm_dpram_addr(uint offset)
+void *cpm_dpram_addr(unsigned long offset)
 {
 	return (void *)&cpm2_immr->im_dprambase[offset];
 }
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 1a84719..098c62c 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -4,27 +4,23 @@
 #
 
 config MMU
-	bool
-	default y
+	def_bool y
 
 config ZONE_DMA
 	def_bool y
 	depends on 64BIT
 
 config LOCKDEP_SUPPORT
-	bool
-	default y
+	def_bool y
 
 config STACKTRACE_SUPPORT
-	bool
-	default y
+	def_bool y
 
 config RWSEM_GENERIC_SPINLOCK
 	bool
 
 config RWSEM_XCHGADD_ALGORITHM
-	bool
-	default y
+	def_bool y
 
 config ARCH_HAS_ILOG2_U32
 	bool
@@ -35,8 +31,7 @@
 	default n
 
 config GENERIC_HWEIGHT
-	bool
-	default y
+	def_bool y
 
 config GENERIC_TIME
 	def_bool y
@@ -55,8 +50,7 @@
 mainmenu "Linux Kernel Configuration"
 
 config S390
-	bool
-	default y
+	def_bool y
 
 source "init/Kconfig"
 
@@ -280,6 +274,10 @@
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
 
+comment "Kernel preemption"
+
+source "kernel/Kconfig.preempt"
+
 source "mm/Kconfig"
 
 config HOLES_IN_ZONE
@@ -320,17 +318,6 @@
 
 comment "Misc"
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	help
-	  This option reduces the latency of the kernel when reacting to
-	  real-time or interactive events by allowing a low priority process to
-	  be preempted even if it is in kernel mode executing a system call.
-	  This allows applications to run more reliably even when the system is
-	  under load.
-
-	  Say N if you are unsure.
-
 config IPL
 	bool "Builtin IPL record support"
 	help
@@ -488,6 +475,8 @@
 	  This can also be compiled as a module, which will be called
 	  appldata_net_sum.o.
 
+source kernel/Kconfig.hz
+
 config NO_IDLE_HZ
 	bool "No HZ timer ticks in idle"
 	help
@@ -535,18 +524,12 @@
 source "net/Kconfig"
 
 config PCMCIA
-	bool
-	default n
+	def_bool n
 
-source "drivers/base/Kconfig"
+config CCW
+	def_bool y
 
-source "drivers/connector/Kconfig"
-
-source "drivers/scsi/Kconfig"
-
-source "drivers/s390/Kconfig"
-
-source "drivers/net/Kconfig"
+source "drivers/Kconfig"
 
 source "fs/Kconfig"
 
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 0e4da8a..485b60c 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.21-rc1
-# Wed Feb 21 10:44:30 2007
+# Linux kernel version: 2.6.21
+# Thu May 10 15:18:19 2007
 #
 CONFIG_MMU=y
 CONFIG_ZONE_DMA=y
@@ -14,6 +14,7 @@
 CONFIG_GENERIC_TIME=y
 CONFIG_GENERIC_BUG=y
 CONFIG_NO_IOMEM=y
+CONFIG_NO_DMA=y
 CONFIG_S390=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
@@ -41,9 +42,11 @@
 # CONFIG_AUDITSYSCALL is not set
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_CPUSETS is not set
 CONFIG_SYSFS_DEPRECATED=y
 # CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SYSCTL=y
@@ -60,12 +63,14 @@
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
 CONFIG_SHMEM=y
-CONFIG_SLAB=y
 CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-# CONFIG_SLOB is not set
 
 #
 # Loadable module support
@@ -128,6 +133,14 @@
 CONFIG_STACK_GUARD=256
 # CONFIG_WARN_STACK is not set
 CONFIG_ARCH_POPULATES_NODE_MAP=y
+
+#
+# Kernel preemption
+#
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_BKL=y
 CONFIG_SELECT_MEMORY_MODEL=y
 CONFIG_FLATMEM_MANUAL=y
 # CONFIG_DISCONTIGMEM_MANUAL is not set
@@ -150,7 +163,6 @@
 #
 # Misc
 #
-CONFIG_PREEMPT=y
 CONFIG_IPL=y
 # CONFIG_IPL_TAPE is not set
 CONFIG_IPL_VM=y
@@ -163,6 +175,11 @@
 CONFIG_VIRT_TIMER=y
 CONFIG_VIRT_CPU_ACCOUNTING=y
 # CONFIG_APPLDATA_BASE is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=100
 CONFIG_NO_IDLE_HZ=y
 CONFIG_NO_IDLE_HZ_INIT=y
 CONFIG_S390_HYPFS_FS=y
@@ -177,7 +194,6 @@
 #
 # Networking options
 #
-# CONFIG_NETDEBUG is not set
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
 CONFIG_UNIX=y
@@ -216,6 +232,7 @@
 CONFIG_IPV6=y
 # CONFIG_IPV6_PRIVACY is not set
 # CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
 # CONFIG_INET6_AH is not set
 # CONFIG_INET6_ESP is not set
 # CONFIG_INET6_IPCOMP is not set
@@ -240,7 +257,12 @@
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-# CONFIG_IP_SCTP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_MSG is not set
+# CONFIG_SCTP_DBG_OBJCNT is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+CONFIG_SCTP_HMAC_MD5=y
 
 #
 # TIPC Configuration (EXPERIMENTAL)
@@ -263,9 +285,6 @@
 #
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_FIFO=y
-CONFIG_NET_SCH_CLK_JIFFIES=y
-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
-# CONFIG_NET_SCH_CLK_CPU is not set
 
 #
 # Queueing/Scheduling
@@ -308,11 +327,14 @@
 #
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_NET_TCPPROBE is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_RFKILL is not set
 # CONFIG_PCMCIA is not set
+CONFIG_CCW=y
+
+#
+# Device Drivers
+#
 
 #
 # Generic Driver Options
@@ -330,6 +352,37 @@
 # CONFIG_CONNECTOR is not set
 
 #
+# Block devices
+#
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# S/390 block device drivers
+#
+CONFIG_BLK_DEV_XPRAM=m
+# CONFIG_DCSSBLK is not set
+CONFIG_DASD=y
+CONFIG_DASD_PROFILE=y
+CONFIG_DASD_ECKD=y
+CONFIG_DASD_FBA=y
+CONFIG_DASD_DIAG=y
+CONFIG_DASD_EER=y
+
+#
+# Misc devices
+#
+# CONFIG_BLINK is not set
+
+#
 # SCSI device support
 #
 # CONFIG_RAID_ATTRS is not set
@@ -356,6 +409,7 @@
 CONFIG_SCSI_CONSTANTS=y
 CONFIG_SCSI_LOGGING=y
 CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_WAIT_SCAN=m
 
 #
 # SCSI Transports
@@ -372,34 +426,6 @@
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_ZFCP=y
-CONFIG_CCW=y
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=m
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-CONFIG_BLK_DEV_NBD=m
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CDROM_PKTCDVD is not set
-
-#
-# S/390 block device drivers
-#
-CONFIG_BLK_DEV_XPRAM=m
-# CONFIG_DCSSBLK is not set
-CONFIG_DASD=y
-CONFIG_DASD_PROFILE=y
-CONFIG_DASD_ECKD=y
-CONFIG_DASD_FBA=y
-CONFIG_DASD_DIAG=y
-CONFIG_DASD_EER=y
-# CONFIG_ATA_OVER_ETH is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -421,56 +447,7 @@
 CONFIG_DM_ZERO=y
 CONFIG_DM_MULTIPATH=y
 # CONFIG_DM_MULTIPATH_EMC is not set
-
-#
-# Character device drivers
-#
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=2048
-# CONFIG_HANGCHECK_TIMER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-
-#
-# S/390 character device drivers
-#
-CONFIG_TN3270=y
-CONFIG_TN3270_TTY=y
-CONFIG_TN3270_FS=m
-CONFIG_TN3270_CONSOLE=y
-CONFIG_TN3215=y
-CONFIG_TN3215_CONSOLE=y
-CONFIG_CCW_CONSOLE=y
-CONFIG_SCLP_TTY=y
-CONFIG_SCLP_CONSOLE=y
-CONFIG_SCLP_VT220_TTY=y
-CONFIG_SCLP_VT220_CONSOLE=y
-CONFIG_SCLP_CPI=m
-CONFIG_S390_TAPE=m
-
-#
-# S/390 tape interface support
-#
-CONFIG_S390_TAPE_BLOCK=y
-
-#
-# S/390 tape hardware support
-#
-CONFIG_S390_TAPE_34XX=m
-# CONFIG_S390_TAPE_3590 is not set
-# CONFIG_VMLOGRDR is not set
-# CONFIG_VMCP is not set
-# CONFIG_MONREADER is not set
-CONFIG_MONWRITER=m
-
-#
-# Cryptographic devices
-#
-CONFIG_ZCRYPT=m
-# CONFIG_ZCRYPT_MONOLITHIC is not set
+# CONFIG_DM_DELAY is not set
 
 #
 # Network device support
@@ -482,10 +459,6 @@
 CONFIG_TUN=m
 
 #
-# PHY device support
-#
-
-#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -498,6 +471,7 @@
 #
 # Ethernet (10000 Mbit)
 #
+CONFIG_MLX4_DEBUG=y
 
 #
 # Token Ring devices
@@ -505,11 +479,6 @@
 # CONFIG_TR is not set
 
 #
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -537,6 +506,56 @@
 # CONFIG_NET_POLL_CONTROLLER is not set
 
 #
+# Character devices
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_R3964 is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# S/390 character device drivers
+#
+CONFIG_TN3270=y
+CONFIG_TN3270_TTY=y
+CONFIG_TN3270_FS=m
+CONFIG_TN3270_CONSOLE=y
+CONFIG_TN3215=y
+CONFIG_TN3215_CONSOLE=y
+CONFIG_CCW_CONSOLE=y
+CONFIG_SCLP=y
+CONFIG_SCLP_TTY=y
+CONFIG_SCLP_CONSOLE=y
+CONFIG_SCLP_VT220_TTY=y
+CONFIG_SCLP_VT220_CONSOLE=y
+CONFIG_SCLP_CPI=m
+CONFIG_S390_TAPE=m
+
+#
+# S/390 tape interface support
+#
+CONFIG_S390_TAPE_BLOCK=y
+
+#
+# S/390 tape hardware support
+#
+CONFIG_S390_TAPE_34XX=m
+# CONFIG_S390_TAPE_3590 is not set
+# CONFIG_VMLOGRDR is not set
+# CONFIG_VMCP is not set
+# CONFIG_MONREADER is not set
+CONFIG_MONWRITER=m
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -628,6 +647,7 @@
 CONFIG_EXPORTFS=y
 CONFIG_NFS_COMMON=y
 CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
@@ -658,6 +678,7 @@
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_KARMA_PARTITION is not set
 # CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
 
 #
 # Native Language Support
@@ -668,8 +689,6 @@
 # Distributed Lock Manager
 #
 CONFIG_DLM=m
-CONFIG_DLM_TCP=y
-# CONFIG_DLM_SCTP is not set
 # CONFIG_DLM_DEBUG is not set
 
 #
@@ -693,7 +712,6 @@
 CONFIG_DEBUG_FS=y
 CONFIG_HEADERS_CHECK=y
 CONFIG_DEBUG_KERNEL=y
-CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
@@ -729,12 +747,13 @@
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_HASH=m
 CONFIG_CRYPTO_MANAGER=y
-# CONFIG_CRYPTO_HMAC is not set
+CONFIG_CRYPTO_HMAC=m
 # CONFIG_CRYPTO_XCBC is not set
 # CONFIG_CRYPTO_NULL is not set
 # CONFIG_CRYPTO_MD4 is not set
-# CONFIG_CRYPTO_MD5 is not set
+CONFIG_CRYPTO_MD5=m
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
@@ -745,6 +764,7 @@
 CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_PCBC=m
 # CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_CRYPTD is not set
 # CONFIG_CRYPTO_DES is not set
 CONFIG_CRYPTO_FCRYPT=m
 # CONFIG_CRYPTO_BLOWFISH is not set
@@ -771,6 +791,8 @@
 # CONFIG_CRYPTO_DES_S390 is not set
 # CONFIG_CRYPTO_AES_S390 is not set
 CONFIG_S390_PRNG=m
+CONFIG_ZCRYPT=m
+# CONFIG_ZCRYPT_MONOLITHIC is not set
 
 #
 # Library routines
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c
index ba5d316..8e1ea1c 100644
--- a/arch/s390/hypfs/inode.c
+++ b/arch/s390/hypfs/inode.c
@@ -477,7 +477,7 @@
 			goto fail_diag;
 		}
 	}
-	kset_set_kset_s(&s390_subsys, hypervisor_subsys);
+	kobj_set_kset_s(&s390_subsys, hypervisor_subsys);
 	rc = subsystem_register(&s390_subsys);
 	if (rc)
 		goto fail_sysfs;
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c
index 0741d91..d1c76fe 100644
--- a/arch/s390/kernel/audit.c
+++ b/arch/s390/kernel/audit.c
@@ -23,6 +23,20 @@
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_COMPAT
+	if (arch == AUDIT_ARCH_S390)
+		return 1;
+#endif
+	return 0;
+}
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_COMPAT
@@ -51,15 +65,18 @@
 	extern __u32 s390_write_class[];
 	extern __u32 s390_read_class[];
 	extern __u32 s390_chattr_class[];
+	extern __u32 s390_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, s390_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c
index 16d9436..0569f51 100644
--- a/arch/s390/kernel/compat_audit.c
+++ b/arch/s390/kernel/compat_audit.c
@@ -21,6 +21,11 @@
 ~0U
 };
 
+unsigned s390_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int s390_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 0ea048d..367caf9 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -816,23 +816,23 @@
 {
 	int rc;
 
-	rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+	rc = sysfs_create_group(&ipl_subsys.kobj,
 				&ipl_fcp_attr_group);
 	if (rc)
 		goto out;
-	rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
 				   &ipl_parameter_attr);
 	if (rc)
 		goto out_ipl_parm;
-	rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj,
+	rc = sysfs_create_bin_file(&ipl_subsys.kobj,
 				   &ipl_scp_data_attr);
 	if (!rc)
 		goto out;
 
-	sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr);
+	sysfs_remove_bin_file(&ipl_subsys.kobj, &ipl_parameter_attr);
 
 out_ipl_parm:
-	sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
+	sysfs_remove_group(&ipl_subsys.kobj, &ipl_fcp_attr_group);
 out:
 	return rc;
 }
@@ -846,7 +846,7 @@
 		return rc;
 	switch (ipl_info.type) {
 	case IPL_TYPE_CCW:
-		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+		rc = sysfs_create_group(&ipl_subsys.kobj,
 					&ipl_ccw_attr_group);
 		break;
 	case IPL_TYPE_FCP:
@@ -854,11 +854,11 @@
 		rc = ipl_register_fcp_files();
 		break;
 	case IPL_TYPE_NSS:
-		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+		rc = sysfs_create_group(&ipl_subsys.kobj,
 					&ipl_nss_attr_group);
 		break;
 	default:
-		rc = sysfs_create_group(&ipl_subsys.kset.kobj,
+		rc = sysfs_create_group(&ipl_subsys.kobj,
 					&ipl_unknown_attr_group);
 		break;
 	}
@@ -885,7 +885,7 @@
 
 	if (!MACHINE_IS_VM)
 		return 0;
-	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group);
+	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_nss_attr_group);
 	if (rc)
 		return rc;
 	strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
@@ -900,7 +900,7 @@
 	reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!reipl_block_ccw)
 		return -ENOMEM;
-	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_ccw_attr_group);
+	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_ccw_attr_group);
 	if (rc) {
 		free_page((unsigned long)reipl_block_ccw);
 		return rc;
@@ -938,7 +938,7 @@
 	reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!reipl_block_fcp)
 		return -ENOMEM;
-	rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_fcp_attr_group);
+	rc = sysfs_create_group(&reipl_subsys.kobj, &reipl_fcp_attr_group);
 	if (rc) {
 		free_page((unsigned long)reipl_block_fcp);
 		return rc;
@@ -990,7 +990,7 @@
 	dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!dump_block_ccw)
 		return -ENOMEM;
-	rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_ccw_attr_group);
+	rc = sysfs_create_group(&dump_subsys.kobj, &dump_ccw_attr_group);
 	if (rc) {
 		free_page((unsigned long)dump_block_ccw);
 		return rc;
@@ -1014,7 +1014,7 @@
 	dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
 	if (!dump_block_fcp)
 		return -ENOMEM;
-	rc = sysfs_create_group(&dump_subsys.kset.kobj, &dump_fcp_attr_group);
+	rc = sysfs_create_group(&dump_subsys.kobj, &dump_fcp_attr_group);
 	if (rc) {
 		free_page((unsigned long)dump_block_fcp);
 		return rc;
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 8b924b3..d855cdb 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -253,7 +253,10 @@
 			 unsigned long address, unsigned long error_code)
 {
 	u16 instruction;
-	int rc, compat;
+	int rc;
+#ifdef CONFIG_COMPAT
+	int compat;
+#endif
 
 	pagefault_disable();
 	rc = __get_user(instruction, (u16 __user *) regs->psw.addr);
diff --git a/arch/sparc64/kernel/audit.c b/arch/sparc64/kernel/audit.c
index aef19cc..24d7f4b 100644
--- a/arch/sparc64/kernel/audit.c
+++ b/arch/sparc64/kernel/audit.c
@@ -23,6 +23,20 @@
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_SPARC32_COMPAT
+	if (arch == AUDIT_ARCH_SPARC)
+		return 1;
+#endif
+	return 0;
+}
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_SPARC32_COMPAT
@@ -51,15 +65,18 @@
 	extern __u32 sparc32_write_class[];
 	extern __u32 sparc32_read_class[];
 	extern __u32 sparc32_chattr_class[];
+	extern __u32 sparc32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, sparc32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, sparc32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, sparc32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, sparc32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, sparc32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
diff --git a/arch/sparc64/kernel/compat_audit.c b/arch/sparc64/kernel/compat_audit.c
index cca96c9..c197948 100644
--- a/arch/sparc64/kernel/compat_audit.c
+++ b/arch/sparc64/kernel/compat_audit.c
@@ -20,6 +20,11 @@
 ~0U
 };
 
+unsigned sparc32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int sparc32_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
index d85e1ed..cf9a751 100644
--- a/arch/sparc64/kernel/pci.c
+++ b/arch/sparc64/kernel/pci.c
@@ -377,7 +377,7 @@
 	const char *type;
 	u32 class;
 
-	dev = kzalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	dev = alloc_pci_dev();
 	if (!dev)
 		return NULL;
 
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c
index 76faaa8..f974fef 100644
--- a/arch/sparc64/kernel/pci_common.c
+++ b/arch/sparc64/kernel/pci_common.c
@@ -14,6 +14,200 @@
 #include <asm/oplib.h>
 
 #include "pci_impl.h"
+#include "pci_sun4v.h"
+
+static int config_out_of_range(struct pci_pbm_info *pbm,
+			       unsigned long bus,
+			       unsigned long devfn,
+			       unsigned long reg)
+{
+	if (bus < pbm->pci_first_busno ||
+	    bus > pbm->pci_last_busno)
+		return 1;
+	return 0;
+}
+
+static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
+				 unsigned long bus,
+				 unsigned long devfn,
+				 unsigned long reg)
+{
+	unsigned long rbits = pbm->config_space_reg_bits;
+
+	if (config_out_of_range(pbm, bus, devfn, reg))
+		return NULL;
+
+	reg = (reg & ((1 << rbits) - 1));
+	devfn <<= rbits;
+	bus <<= rbits + 8;
+
+	return (void *)	(pbm->config_space | bus | devfn | reg);
+}
+
+static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+			      int where, int size, u32 *value)
+{
+	struct pci_pbm_info *pbm = bus_dev->sysdata;
+	unsigned char bus = bus_dev->number;
+	u32 *addr;
+	u16 tmp16;
+	u8 tmp8;
+
+	if (bus_dev == pbm->pci_bus && devfn == 0x00)
+		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
+						    size, value);
+
+	switch (size) {
+	case 1:
+		*value = 0xff;
+		break;
+	case 2:
+		*value = 0xffff;
+		break;
+	case 4:
+		*value = 0xffffffff;
+		break;
+	}
+
+	addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	switch (size) {
+	case 1:
+		pci_config_read8((u8 *)addr, &tmp8);
+		*value = (u32) tmp8;
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_read_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read16((u16 *)addr, &tmp16);
+		*value = (u32) tmp16;
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_read_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_read32(addr, value);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+			       int where, int size, u32 value)
+{
+	struct pci_pbm_info *pbm = bus_dev->sysdata;
+	unsigned char bus = bus_dev->number;
+	u32 *addr;
+
+	if (bus_dev == pbm->pci_bus && devfn == 0x00)
+		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
+						     size, value);
+	addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	switch (size) {
+	case 1:
+		pci_config_write8((u8 *)addr, value);
+		break;
+
+	case 2:
+		if (where & 0x01) {
+			printk("pci_write_config_word: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write16((u16 *)addr, value);
+		break;
+
+	case 4:
+		if (where & 0x03) {
+			printk("pci_write_config_dword: misaligned reg [%x]\n",
+			       where);
+			return PCIBIOS_SUCCESSFUL;
+		}
+		pci_config_write32(addr, value);
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sun4u_pci_ops = {
+	.read =		sun4u_read_pci_cfg,
+	.write =	sun4u_write_pci_cfg,
+};
+
+static int sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+			      int where, int size, u32 *value)
+{
+	struct pci_pbm_info *pbm = bus_dev->sysdata;
+	u32 devhandle = pbm->devhandle;
+	unsigned int bus = bus_dev->number;
+	unsigned int device = PCI_SLOT(devfn);
+	unsigned int func = PCI_FUNC(devfn);
+	unsigned long ret;
+
+	if (bus_dev == pbm->pci_bus && devfn == 0x00)
+		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
+						    size, value);
+	if (config_out_of_range(pbm, bus, devfn, where)) {
+		ret = ~0UL;
+	} else {
+		ret = pci_sun4v_config_get(devhandle,
+				HV_PCI_DEVICE_BUILD(bus, device, func),
+				where, size);
+	}
+	switch (size) {
+	case 1:
+		*value = ret & 0xff;
+		break;
+	case 2:
+		*value = ret & 0xffff;
+		break;
+	case 4:
+		*value = ret & 0xffffffff;
+		break;
+	};
+
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
+			       int where, int size, u32 value)
+{
+	struct pci_pbm_info *pbm = bus_dev->sysdata;
+	u32 devhandle = pbm->devhandle;
+	unsigned int bus = bus_dev->number;
+	unsigned int device = PCI_SLOT(devfn);
+	unsigned int func = PCI_FUNC(devfn);
+	unsigned long ret;
+
+	if (bus_dev == pbm->pci_bus && devfn == 0x00)
+		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
+						     size, value);
+	if (config_out_of_range(pbm, bus, devfn, where)) {
+		/* Do nothing. */
+	} else {
+		ret = pci_sun4v_config_put(devhandle,
+				HV_PCI_DEVICE_BUILD(bus, device, func),
+				where, size, value);
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops sun4v_pci_ops = {
+	.read =		sun4v_read_pci_cfg,
+	.write =	sun4v_write_pci_cfg,
+};
 
 void pci_get_pbm_props(struct pci_pbm_info *pbm)
 {
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c
index 2e0eb4e..9198c1a 100644
--- a/arch/sparc64/kernel/pci_fire.c
+++ b/arch/sparc64/kernel/pci_fire.c
@@ -27,138 +27,6 @@
 			       "i" (ASI_PHYS_BYPASS_EC_E) \
 			     : "memory")
 
-/* Fire config space address format is nearly identical to
- * that of SCHIZO and PSYCHO, except that in order to accomodate
- * PCI-E extended config space the encoding can handle 12 bits
- * of register address:
- *
- *  32     28 27 20 19    15 14      12 11  2  1 0
- * -------------------------------------------------
- * |0 0 0 0 0| bus | device | function | reg | 0 0 |
- * -------------------------------------------------
- */
-#define FIRE_CONFIG_BASE(PBM)	((PBM)->config_space)
-#define FIRE_CONFIG_ENCODE(BUS, DEVFN, REG)	\
-	(((unsigned long)(BUS)   << 20) |	\
-	 ((unsigned long)(DEVFN) << 12)  |	\
-	 ((unsigned long)(REG)))
-
-static void *fire_pci_config_mkaddr(struct pci_pbm_info *pbm,
-				      unsigned char bus,
-				      unsigned int devfn,
-				      int where)
-{
-	if (!pbm)
-		return NULL;
-	return (void *)
-		(FIRE_CONFIG_BASE(pbm) |
-		 FIRE_CONFIG_ENCODE(bus, devfn, where));
-}
-
-/* FIRE PCI configuration space accessors. */
-
-static int fire_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-			     int where, int size, u32 *value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-	u16 tmp16;
-	u8 tmp8;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
-						    size, value);
-	switch (size) {
-	case 1:
-		*value = 0xff;
-		break;
-	case 2:
-		*value = 0xffff;
-		break;
-	case 4:
-		*value = 0xffffffff;
-		break;
-	}
-
-	addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		pci_config_read8((u8 *)addr, &tmp8);
-		*value = tmp8;
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_read_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read16((u16 *)addr, &tmp16);
-		*value = tmp16;
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_read_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-
-		pci_config_read32(addr, value);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int fire_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-			      int where, int size, u32 value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
-						     size, value);
-	addr = fire_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		pci_config_write8((u8 *)addr, value);
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_write_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_write16((u16 *)addr, value);
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_write_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-
-		pci_config_write32(addr, value);
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_fire_ops = {
-	.read	=	fire_read_pci_cfg,
-	.write	=	fire_write_pci_cfg,
-};
-
 static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
 {
 	pbm->pci_bus = pci_scan_one_pbm(pbm);
@@ -314,7 +182,8 @@
 	pci_pbm_root = pbm;
 
 	pbm->scan_bus = pci_fire_scan_bus;
-	pbm->pci_ops = &pci_fire_ops;
+	pbm->pci_ops = &sun4u_pci_ops;
+	pbm->config_space_reg_bits = 12;
 
 	pbm->index = pci_num_pbms++;
 
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h
index 8e38023..f660c2b 100644
--- a/arch/sparc64/kernel/pci_impl.h
+++ b/arch/sparc64/kernel/pci_impl.h
@@ -77,6 +77,9 @@
 	/* Base of PCI Config space, can be per-PBM or shared. */
 	unsigned long			config_space;
 
+	/* This will be 12 on PCI-E controllers, 8 elsewhere.  */
+	unsigned long			config_space_reg_bits;
+
 	/* State of 66MHz capabilities on this PBM. */
 	int				is_66mhz_capable;
 	int				all_devs_66mhz;
@@ -156,4 +159,7 @@
 extern void pci_config_write16(u16 *addr, u16 val);
 extern void pci_config_write32(u32 *addr, u32 val);
 
+extern struct pci_ops sun4u_pci_ops;
+extern struct pci_ops sun4v_pci_ops;
+
 #endif /* !(PCI_IMPL_H) */
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 2edcb1d..598393a2 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -94,122 +94,6 @@
 		 PSYCHO_CONFIG_ENCODE(bus, devfn, where));
 }
 
-static int psycho_out_of_range(struct pci_pbm_info *pbm,
-			       unsigned char bus,
-			       unsigned char devfn)
-{
-	return ((bus == pbm->pci_first_busno) &&
-		PCI_SLOT(devfn) > 8);
-}
-
-/* PSYCHO PCI configuration space accessors. */
-
-static int psycho_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-			       int where, int size, u32 *value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-	u16 tmp16;
-	u8 tmp8;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
-						    size, value);
-
-	switch (size) {
-	case 1:
-		*value = 0xff;
-		break;
-	case 2:
-		*value = 0xffff;
-		break;
-	case 4:
-		*value = 0xffffffff;
-		break;
-	}
-
-	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (psycho_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-	switch (size) {
-	case 1:
-		pci_config_read8((u8 *)addr, &tmp8);
-		*value = (u32) tmp8;
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_read_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read16((u16 *)addr, &tmp16);
-		*value = (u32) tmp16;
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_read_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read32(addr, value);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int psycho_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-				int where, int size, u32 value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
-						     size, value);
-	addr = psycho_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (psycho_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		pci_config_write8((u8 *)addr, value);
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_write_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_write16((u16 *)addr, value);
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_write_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_write32(addr, value);
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops psycho_ops = {
-	.read =		psycho_read_pci_cfg,
-	.write =	psycho_write_pci_cfg,
-};
-
 /* PSYCHO error handling support. */
 enum psycho_error_type {
 	UE_ERR, CE_ERR, PCI_ERR
@@ -1089,7 +973,8 @@
 	pci_pbm_root = pbm;
 
 	pbm->scan_bus = psycho_scan_bus;
-	pbm->pci_ops = &psycho_ops;
+	pbm->pci_ops = &sun4u_pci_ops;
+	pbm->config_space_reg_bits = 8;
 
 	pbm->index = pci_num_pbms++;
 
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 4cefe6e..e237779 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -205,294 +205,9 @@
 #define SABRE_MEMSPACE		0x100000000UL
 #define SABRE_MEMSPACE_SIZE	0x07fffffffUL
 
-/* UltraSparc-IIi Programmer's Manual, page 325, PCI
- * configuration space address format:
- * 
- *  32             24 23 16 15    11 10       8 7   2  1 0
- * ---------------------------------------------------------
- * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 |
- * ---------------------------------------------------------
- */
-#define SABRE_CONFIG_BASE(PBM)	\
-	((PBM)->config_space | (1UL << 24))
-#define SABRE_CONFIG_ENCODE(BUS, DEVFN, REG)	\
-	(((unsigned long)(BUS)   << 16) |	\
-	 ((unsigned long)(DEVFN) << 8)  |	\
-	 ((unsigned long)(REG)))
-
 static int hummingbird_p;
 static struct pci_bus *sabre_root_bus;
 
-static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
-				     unsigned char bus,
-				     unsigned int devfn,
-				     int where)
-{
-	if (!pbm)
-		return NULL;
-	return (void *)
-		(SABRE_CONFIG_BASE(pbm) |
-		 SABRE_CONFIG_ENCODE(bus, devfn, where));
-}
-
-static int sabre_out_of_range(unsigned char devfn)
-{
-	if (hummingbird_p)
-		return 0;
-
-	return (((PCI_SLOT(devfn) == 0) && (PCI_FUNC(devfn) > 0)) ||
-		((PCI_SLOT(devfn) == 1) && (PCI_FUNC(devfn) > 1)) ||
-		(PCI_SLOT(devfn) > 1));
-}
-
-static int __sabre_out_of_range(struct pci_pbm_info *pbm,
-				unsigned char bus,
-				unsigned char devfn)
-{
-	if (hummingbird_p)
-		return 0;
-
-	return ((pbm->parent == 0) ||
-		((pbm == &pbm->parent->pbm_A) &&
-		 (bus == pbm->pci_first_busno) &&
-		 PCI_SLOT(devfn) > 8));
-}
-
-static int __sabre_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-				int where, int size, u32 *value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-	u16 tmp16;
-	u8 tmp8;
-
-	switch (size) {
-	case 1:
-		*value = 0xff;
-		break;
-	case 2:
-		*value = 0xffff;
-		break;
-	case 4:
-		*value = 0xffffffff;
-		break;
-	}
-
-	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (__sabre_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		pci_config_read8((u8 *) addr, &tmp8);
-		*value = tmp8;
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_read_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read16((u16 *) addr, &tmp16);
-		*value = tmp16;
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_read_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read32(addr, value);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int sabre_read_pci_cfg(struct pci_bus *bus, unsigned int devfn,
-			      int where, int size, u32 *value)
-{
-	struct pci_pbm_info *pbm = bus->sysdata;
-
-	if (bus == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_read_pci_cfg(bus, devfn, where,
-						    size, value);
-
-	if (!bus->number && sabre_out_of_range(devfn)) {
-		switch (size) {
-		case 1:
-			*value = 0xff;
-			break;
-		case 2:
-			*value = 0xffff;
-			break;
-		case 4:
-			*value = 0xffffffff;
-			break;
-		}
-		return PCIBIOS_SUCCESSFUL;
-	}
-
-	if (bus->number || PCI_SLOT(devfn))
-		return __sabre_read_pci_cfg(bus, devfn, where, size, value);
-
-	/* When accessing PCI config space of the PCI controller itself (bus
-	 * 0, device slot 0, function 0) there are restrictions.  Each
-	 * register must be accessed as it's natural size.  Thus, for example
-	 * the Vendor ID must be accessed as a 16-bit quantity.
-	 */
-
-	switch (size) {
-	case 1:
-		if (where < 8) {
-			u32 tmp32;
-			u16 tmp16;
-
-			__sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
-			tmp16 = (u16) tmp32;
-			if (where & 1)
-				*value = tmp16 >> 8;
-			else
-				*value = tmp16 & 0xff;
-		} else
-			return __sabre_read_pci_cfg(bus, devfn, where, 1, value);
-		break;
-
-	case 2:
-		if (where < 8)
-			return __sabre_read_pci_cfg(bus, devfn, where, 2, value);
-		else {
-			u32 tmp32;
-			u8 tmp8;
-
-			__sabre_read_pci_cfg(bus, devfn, where, 1, &tmp32);
-			tmp8 = (u8) tmp32;
-			*value = tmp8;
-			__sabre_read_pci_cfg(bus, devfn, where + 1, 1, &tmp32);
-			tmp8 = (u8) tmp32;
-			*value |= tmp8 << 8;
-		}
-		break;
-
-	case 4: {
-		u32 tmp32;
-		u16 tmp16;
-
-		sabre_read_pci_cfg(bus, devfn, where, 2, &tmp32);
-		tmp16 = (u16) tmp32;
-		*value = tmp16;
-		sabre_read_pci_cfg(bus, devfn, where + 2, 2, &tmp32);
-		tmp16 = (u16) tmp32;
-		*value |= tmp16 << 16;
-		break;
-	}
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int __sabre_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-				 int where, int size, u32 value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-
-	addr = sabre_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (__sabre_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		pci_config_write8((u8 *) addr, value);
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_write_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_write16((u16 *) addr, value);
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_write_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_write32(addr, value);
-		break;
-	}
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int sabre_write_pci_cfg(struct pci_bus *bus, unsigned int devfn,
-			       int where, int size, u32 value)
-{
-	struct pci_pbm_info *pbm = bus->sysdata;
-
-	if (bus == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_write_pci_cfg(bus, devfn, where,
-						     size, value);
-
-	if (bus->number)
-		return __sabre_write_pci_cfg(bus, devfn, where, size, value);
-
-	if (sabre_out_of_range(devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		if (where < 8) {
-			u32 tmp32;
-			u16 tmp16;
-
-			__sabre_read_pci_cfg(bus, devfn, where & ~1, 2, &tmp32);
-			tmp16 = (u16) tmp32;
-			if (where & 1) {
-				value &= 0x00ff;
-				value |= tmp16 << 8;
-			} else {
-				value &= 0xff00;
-				value |= tmp16;
-			}
-			tmp32 = (u32) tmp16;
-			return __sabre_write_pci_cfg(bus, devfn, where & ~1, 2, tmp32);
-		} else
-			return __sabre_write_pci_cfg(bus, devfn, where, 1, value);
-		break;
-	case 2:
-		if (where < 8)
-			return __sabre_write_pci_cfg(bus, devfn, where, 2, value);
-		else {
-			__sabre_write_pci_cfg(bus, devfn, where, 1, value & 0xff);
-			__sabre_write_pci_cfg(bus, devfn, where + 1, 1, value >> 8);
-		}
-		break;
-	case 4:
-		sabre_write_pci_cfg(bus, devfn, where, 2, value & 0xffff);
-		sabre_write_pci_cfg(bus, devfn, where + 2, 2, value >> 16);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops sabre_ops = {
-	.read =		sabre_read_pci_cfg,
-	.write =	sabre_write_pci_cfg,
-};
-
 /* SABRE error handling support. */
 static void sabre_check_iommu_error(struct pci_pbm_info *pbm,
 				    unsigned long afsr,
@@ -1010,7 +725,8 @@
 	printk("%s: SABRE PCI Bus Module\n", pbm->name);
 
 	pbm->scan_bus = sabre_scan_bus;
-	pbm->pci_ops = &sabre_ops;
+	pbm->pci_ops = &sun4u_pci_ops;
+	pbm->config_space_reg_bits = 8;
 
 	pbm->index = pci_num_pbms++;
 
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index e375d72..ae76898 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -104,125 +104,6 @@
 		 SCHIZO_CONFIG_ENCODE(bus, devfn, where));
 }
 
-/* Just make sure the bus number is in range.  */
-static int schizo_out_of_range(struct pci_pbm_info *pbm,
-			       unsigned char bus,
-			       unsigned char devfn)
-{
-	if (bus < pbm->pci_first_busno ||
-	    bus > pbm->pci_last_busno)
-		return 1;
-	return 0;
-}
-
-/* SCHIZO PCI configuration space accessors. */
-
-static int schizo_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-			       int where, int size, u32 *value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-	u16 tmp16;
-	u8 tmp8;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
-						    size, value);
-	switch (size) {
-	case 1:
-		*value = 0xff;
-		break;
-	case 2:
-		*value = 0xffff;
-		break;
-	case 4:
-		*value = 0xffffffff;
-		break;
-	}
-
-	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (schizo_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-	switch (size) {
-	case 1:
-		pci_config_read8((u8 *)addr, &tmp8);
-		*value = tmp8;
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_read_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read16((u16 *)addr, &tmp16);
-		*value = tmp16;
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_read_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_read32(addr, value);
-		break;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int schizo_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-				int where, int size, u32 value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	unsigned char bus = bus_dev->number;
-	u32 *addr;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
-						     size, value);
-	addr = schizo_pci_config_mkaddr(pbm, bus, devfn, where);
-	if (!addr)
-		return PCIBIOS_SUCCESSFUL;
-
-	if (schizo_out_of_range(pbm, bus, devfn))
-		return PCIBIOS_SUCCESSFUL;
-
-	switch (size) {
-	case 1:
-		pci_config_write8((u8 *)addr, value);
-		break;
-
-	case 2:
-		if (where & 0x01) {
-			printk("pci_write_config_word: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-		pci_config_write16((u16 *)addr, value);
-		break;
-
-	case 4:
-		if (where & 0x03) {
-			printk("pci_write_config_dword: misaligned reg [%x]\n",
-			       where);
-			return PCIBIOS_SUCCESSFUL;
-		}
-
-		pci_config_write32(addr, value);
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops schizo_ops = {
-	.read =		schizo_read_pci_cfg,
-	.write =	schizo_write_pci_cfg,
-};
-
 /* SCHIZO error handling support. */
 enum schizo_error_type {
 	UE_ERR, CE_ERR, PCI_ERR, SAFARI_ERR
@@ -1494,7 +1375,8 @@
 	pci_pbm_root = pbm;
 
 	pbm->scan_bus = schizo_scan_bus;
-	pbm->pci_ops = &schizo_ops;
+	pbm->pci_ops = &sun4u_pci_ops;
+	pbm->config_space_reg_bits = 8;
 
 	pbm->index = pci_num_pbms++;
 
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 0c76a88..34df404 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -593,89 +593,6 @@
 	.dma_sync_sg_for_cpu		= pci_4v_dma_sync_sg_for_cpu,
 };
 
-static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
-{
-	if (bus < pbm->pci_first_busno ||
-	    bus > pbm->pci_last_busno)
-		return 1;
-	return 0;
-}
-
-static int pci_sun4v_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-				  int where, int size, u32 *value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	u32 devhandle = pbm->devhandle;
-	unsigned int bus = bus_dev->number;
-	unsigned int device = PCI_SLOT(devfn);
-	unsigned int func = PCI_FUNC(devfn);
-	unsigned long ret;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
-						    size, value);
-	if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
-		ret = ~0UL;
-	} else {
-		ret = pci_sun4v_config_get(devhandle,
-				HV_PCI_DEVICE_BUILD(bus, device, func),
-				where, size);
-#if 0
-		printk("rcfg: [%x:%x:%x:%d]=[%lx]\n",
-		       devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
-		       where, size, ret);
-#endif
-	}
-	switch (size) {
-	case 1:
-		*value = ret & 0xff;
-		break;
-	case 2:
-		*value = ret & 0xffff;
-		break;
-	case 4:
-		*value = ret & 0xffffffff;
-		break;
-	};
-
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int pci_sun4v_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
-				   int where, int size, u32 value)
-{
-	struct pci_pbm_info *pbm = bus_dev->sysdata;
-	u32 devhandle = pbm->devhandle;
-	unsigned int bus = bus_dev->number;
-	unsigned int device = PCI_SLOT(devfn);
-	unsigned int func = PCI_FUNC(devfn);
-	unsigned long ret;
-
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
-						     size, value);
-	if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
-		/* Do nothing. */
-	} else {
-		ret = pci_sun4v_config_put(devhandle,
-				HV_PCI_DEVICE_BUILD(bus, device, func),
-				where, size, value);
-#if 0
-		printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n",
-		       devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
-		       where, size, value, ret);
-#endif
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_sun4v_ops = {
-	.read =		pci_sun4v_read_pci_cfg,
-	.write =	pci_sun4v_write_pci_cfg,
-};
-
-
 static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
 {
 	struct property *prop;
@@ -1238,7 +1155,8 @@
 	pci_pbm_root = pbm;
 
 	pbm->scan_bus = pci_sun4v_scan_bus;
-	pbm->pci_ops = &pci_sun4v_ops;
+	pbm->pci_ops = &sun4v_pci_ops;
+	pbm->config_space_reg_bits = 12;
 
 	pbm->index = pci_num_pbms++;
 
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index c54d4d8..b7976b1 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -1636,10 +1636,21 @@
 
 static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
 {
+	struct device_node *ret = NULL, *prev_sibling = NULL;
 	struct device_node *dp;
 
-	dp = create_node(node, parent);
-	if (dp) {
+	while (1) {
+		dp = create_node(node, parent);
+		if (!dp)
+			break;
+
+		if (prev_sibling)
+			prev_sibling->sibling = dp;
+
+		if (!ret)
+			ret = dp;
+		prev_sibling = dp;
+
 		*(*nextp) = dp;
 		*nextp = &dp->allnext;
 
@@ -1648,10 +1659,10 @@
 
 		dp->child = build_tree(dp, prom_getchild(node), nextp);
 
-		dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
+		node = prom_getsibling(node);
 	}
 
-	return dp;
+	return ret;
 }
 
 void __init prom_build_devicetree(void)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index b9c0f30..c504312 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -277,7 +277,8 @@
 
 config KERNEL_STACK_ORDER
 	int "Kernel stack size order"
-	default 2
+	default 1 if 64BIT
+	default 0 if !64BIT
 	help
 	This option determines the size of UML kernel stacks.  They will
 	be 1 << order pages.  The default is OK unless you're running Valgrind
diff --git a/arch/um/defconfig b/arch/um/defconfig
index f938fa8..a54d0ef 100644
--- a/arch/um/defconfig
+++ b/arch/um/defconfig
@@ -86,7 +86,7 @@
 # CONFIG_MAGIC_SYSRQ is not set
 CONFIG_NEST_LEVEL=0
 # CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_STACK_ORDER=2
+CONFIG_KERNEL_STACK_ORDER=0
 CONFIG_UML_REAL_TIME_CLOCK=y
 
 #
diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
index 5593a80..541f4a8 100644
--- a/arch/um/include/common-offsets.h
+++ b/arch/um/include/common-offsets.h
@@ -28,3 +28,5 @@
 
 /* For crypto assembler code. */
 DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
+
+DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
index 50a4969..8d7f7c1 100644
--- a/arch/um/include/kern_util.h
+++ b/arch/um/include/kern_util.h
@@ -117,4 +117,7 @@
 
 extern void copy_sc(union uml_pt_regs *regs, void *from);
 
+unsigned long to_irq_stack(int sig, unsigned long *mask_out);
+unsigned long from_irq_stack(int nested);
+
 #endif
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 688d181..4d9fb263 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -272,7 +272,6 @@
 
 /* util.c */
 extern void stack_protections(unsigned long address);
-extern void task_protections(unsigned long address);
 extern int raw(int fd);
 extern void setup_machinename(char *machine_out);
 extern void setup_hostinfo(char *buf, int len);
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index e36f92b..87a4e44 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -97,6 +97,8 @@
   .data           : {
     . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
     *(.data.init_task)
+    . = ALIGN(KERNEL_STACK_SIZE);
+    *(.data.init_irqstack)
     *(.data .data.* .gnu.linkonce.d.*)
     SORT(CONSTRUCTORS)
   }
diff --git a/arch/um/kernel/init_task.c b/arch/um/kernel/init_task.c
index cda91aa..d4f1d1a 100644
--- a/arch/um/kernel/init_task.c
+++ b/arch/um/kernel/init_task.c
@@ -1,5 +1,5 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+/*
+ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,intel.linux}.com)
  * Licensed under the GPL
  */
 
@@ -33,28 +33,20 @@
 /*
  * Initial thread structure.
  *
- * We need to make sure that this is 16384-byte aligned due to the
+ * We need to make sure that this is aligned due to the
  * way process stacks are handled. This is done by having a special
  * "init_task" linker map entry..
  */
 
-union thread_union init_thread_union 
-__attribute__((__section__(".data.init_task"))) = 
-{ INIT_THREAD_INFO(init_task) };
+union thread_union init_thread_union
+	__attribute__((__section__(".data.init_task"))) =
+		{ INIT_THREAD_INFO(init_task) };
+
+union thread_union cpu0_irqstack
+	__attribute__((__section__(".data.init_irqstack"))) =
+		{ INIT_THREAD_INFO(init_task) };
 
 void unprotect_stack(unsigned long stack)
 {
-	os_protect_memory((void *) stack, (1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE,
-		       1, 1, 0);
+	os_protect_memory((void *) stack, THREAD_SIZE, 1, 1, 0);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 8f2ed36..dba04d8 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  * Derived (i.e. mostly copied) from arch/i386/kernel/irq.c:
@@ -32,6 +32,7 @@
 #include "sigio.h"
 #include "um_malloc.h"
 #include "misc_constants.h"
+#include "as-layout.h"
 
 /*
  * Generic, controller-independent functions:
@@ -53,7 +54,7 @@
 	if (i < NR_IRQS) {
 		spin_lock_irqsave(&irq_desc[i].lock, flags);
 		action = irq_desc[i].action;
-		if (!action) 
+		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
@@ -468,3 +469,113 @@
  out:
 	return err;
 }
+
+/*
+ * IRQ stack entry and exit:
+ *
+ * Unlike i386, UML doesn't receive IRQs on the normal kernel stack
+ * and switch over to the IRQ stack after some preparation.  We use
+ * sigaltstack to receive signals on a separate stack from the start.
+ * These two functions make sure the rest of the kernel won't be too
+ * upset by being on a different stack.  The IRQ stack has a
+ * thread_info structure at the bottom so that current et al continue
+ * to work.
+ *
+ * to_irq_stack copies the current task's thread_info to the IRQ stack
+ * thread_info and sets the tasks's stack to point to the IRQ stack.
+ *
+ * from_irq_stack copies the thread_info struct back (flags may have
+ * been modified) and resets the task's stack pointer.
+ *
+ * Tricky bits -
+ *
+ * What happens when two signals race each other?  UML doesn't block
+ * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal
+ * could arrive while a previous one is still setting up the
+ * thread_info.
+ *
+ * There are three cases -
+ *     The first interrupt on the stack - sets up the thread_info and
+ * handles the interrupt
+ *     A nested interrupt interrupting the copying of the thread_info -
+ * can't handle the interrupt, as the stack is in an unknown state
+ *     A nested interrupt not interrupting the copying of the
+ * thread_info - doesn't do any setup, just handles the interrupt
+ *
+ * The first job is to figure out whether we interrupted stack setup.
+ * This is done by xchging the signal mask with thread_info->pending.
+ * If the value that comes back is zero, then there is no setup in
+ * progress, and the interrupt can be handled.  If the value is
+ * non-zero, then there is stack setup in progress.  In order to have
+ * the interrupt handled, we leave our signal in the mask, and it will
+ * be handled by the upper handler after it has set up the stack.
+ *
+ * Next is to figure out whether we are the outer handler or a nested
+ * one.  As part of setting up the stack, thread_info->real_thread is
+ * set to non-NULL (and is reset to NULL on exit).  This is the
+ * nesting indicator.  If it is non-NULL, then the stack is already
+ * set up and the handler can run.
+ */
+
+static unsigned long pending_mask;
+
+unsigned long to_irq_stack(int sig, unsigned long *mask_out)
+{
+	struct thread_info *ti;
+	unsigned long mask, old;
+	int nested;
+
+	mask = xchg(&pending_mask, 1 << sig);
+	if(mask != 0){
+		/* If any interrupts come in at this point, we want to
+		 * make sure that their bits aren't lost by our
+		 * putting our bit in.  So, this loop accumulates bits
+		 * until xchg returns the same value that we put in.
+		 * When that happens, there were no new interrupts,
+		 * and pending_mask contains a bit for each interrupt
+		 * that came in.
+		 */
+		old = 1 << sig;
+		do {
+			old |= mask;
+			mask = xchg(&pending_mask, old);
+		} while(mask != old);
+		return 1;
+	}
+
+	ti = current_thread_info();
+	nested = (ti->real_thread != NULL);
+	if(!nested){
+		struct task_struct *task;
+		struct thread_info *tti;
+
+		task = cpu_tasks[ti->cpu].task;
+		tti = task_thread_info(task);
+		*ti = *tti;
+		ti->real_thread = tti;
+		task->stack = ti;
+	}
+
+	mask = xchg(&pending_mask, 0);
+	*mask_out |= mask | nested;
+	return 0;
+}
+
+unsigned long from_irq_stack(int nested)
+{
+	struct thread_info *ti, *to;
+	unsigned long mask;
+
+	ti = current_thread_info();
+
+	pending_mask = 1;
+
+	to = ti->real_thread;
+	current->stack = to;
+	ti->real_thread = NULL;
+	*to = *ti;
+
+	mask = xchg(&pending_mask, 0);
+	return mask & ~1;
+}
+
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index a96ae1a..2a69a7c 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -163,8 +163,12 @@
 
 extern int userspace_pid[];
 
+extern char cpu0_irqstack[];
+
 int start_uml_skas(void)
 {
+	stack_protections((unsigned long) &cpu0_irqstack);
+	set_sigstack(cpu0_irqstack, THREAD_SIZE);
 	if(proc_mm)
 		userspace_pid[0] = start_userspace(0);
 
diff --git a/arch/um/kernel/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c
index 98e2174..40126cb 100644
--- a/arch/um/kernel/tt/exec_kern.c
+++ b/arch/um/kernel/tt/exec_kern.c
@@ -57,7 +57,7 @@
 	enable_timer();
 	free_page(stack);
 	protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
-	task_protections((unsigned long) current_thread);
+	stack_protections((unsigned long) current_thread);
 	force_flush_all();
 	unblock_signals();
 }
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index c631303..74347ad 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -209,7 +209,7 @@
 	if(current->mm != current->parent->mm)
 		protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 
 			       1, 0, 1);
-	task_protections((unsigned long) current_thread);
+	stack_protections((unsigned long) current_thread);
 
 	free_page(current->thread.temp_stack);
 	local_irq_disable();
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 1cf954a..ecc458f 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -459,7 +459,7 @@
 
 	uml_postsetup();
 
-	task_protections((unsigned long) &init_thread_info);
+	stack_protections((unsigned long) &init_thread_info);
 	os_flush_stdout();
 
 	return CHOOSE_MODE(start_uml_tt(), start_uml_skas());
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index f630127..bc59f97 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -59,6 +59,8 @@
   {
     . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
     *(.data.init_task)
+    . = ALIGN(KERNEL_STACK_SIZE);
+    *(.data.init_irqstack)
     *(.data)
     *(.gnu.linkonce.d*)
     CONSTRUCTORS
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 48d4934..18e5c8b 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -61,15 +61,19 @@
 
 static void real_alarm_handler(int sig, struct sigcontext *sc)
 {
+	union uml_pt_regs regs;
+
 	if(sig == SIGALRM)
 		switch_timers(0);
 
-	CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas,
-			 sig, sc);
+	if(sc != NULL)
+		copy_sc(&regs, sc);
+	regs.skas.is_user = 0;
+	unblock_signals();
+	timer_handler(sig, &regs);
 
 	if(sig == SIGALRM)
 		switch_timers(1);
-
 }
 
 void alarm_handler(int sig, struct sigcontext *sc)
@@ -113,6 +117,46 @@
 
 void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
 
+void handle_signal(int sig, struct sigcontext *sc)
+{
+	unsigned long pending = 0;
+
+	do {
+		int nested, bail;
+
+		/*
+		 * pending comes back with one bit set for each
+		 * interrupt that arrived while setting up the stack,
+		 * plus a bit for this interrupt, plus the zero bit is
+		 * set if this is a nested interrupt.
+		 * If bail is true, then we interrupted another
+		 * handler setting up the stack.  In this case, we
+		 * have to return, and the upper handler will deal
+		 * with this interrupt.
+		 */
+		bail = to_irq_stack(sig, &pending);
+		if(bail)
+			return;
+
+		nested = pending & 1;
+		pending &= ~1;
+
+		while((sig = ffs(pending)) != 0){
+			sig--;
+			pending &= ~(1 << sig);
+			(*handlers[sig])(sig, sc);
+		}
+
+		/* Again, pending comes back with a mask of signals
+		 * that arrived while tearing down the stack.  If this
+		 * is non-zero, we just go back, set up the stack
+		 * again, and handle the new interrupts.
+		 */
+		if(!nested)
+			pending = from_irq_stack(nested);
+	} while(pending);
+}
+
 extern void hard_handler(int sig);
 
 void set_handler(int sig, void (*handler)(int), int flags, ...)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 6a0e466..f9d2f85 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -288,7 +288,8 @@
 void userspace(union uml_pt_regs *regs)
 {
 	int err, status, op, pid = userspace_pid[0];
-	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
+	/* To prevent races if using_sysemu changes under us.*/
+	int local_using_sysemu;
 
 	while(1){
 		restore_registers(pid, regs);
@@ -296,7 +297,8 @@
 		/* Now we set local_using_sysemu to be used for one loop */
 		local_using_sysemu = get_using_sysemu();
 
-		op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
+		op = SELECT_PTRACE_OPERATION(local_using_sysemu,
+					     singlestepping(NULL));
 
 		err = ptrace(op, pid, 0, 0);
 		if(err)
@@ -490,8 +492,8 @@
 void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
 {
 	(*buf)[0].JB_IP = (unsigned long) handler;
-	(*buf)[0].JB_SP = (unsigned long) stack +
-		(PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
+	(*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE -
+		sizeof(void *);
 }
 
 #define INIT_JMP_NEW_THREAD 0
@@ -533,8 +535,7 @@
 	case INIT_JMP_NEW_THREAD:
 		(*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
 		(*switch_buf)[0].JB_SP = (unsigned long) stack +
-			(PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
-			sizeof(void *);
+			UM_THREAD_SIZE - sizeof(void *);
 		break;
 	case INIT_JMP_CALLBACK:
 		(*cb_proc)(cb_arg);
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
index 0d3eae5..f311609 100644
--- a/arch/um/os-Linux/sys-i386/signal.c
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -1,15 +1,13 @@
 /*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
 #include <signal.h>
 
-extern void (*handlers[])(int sig, struct sigcontext *sc);
+extern void handle_signal(int sig, struct sigcontext *sc);
 
 void hard_handler(int sig)
 {
-	struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
-
-	(*handlers[sig])(sig, sc);
+	handle_signal(sig, (struct sigcontext *) (&sig + 1));
 }
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
index 3f369e5..82a3888 100644
--- a/arch/um/os-Linux/sys-x86_64/signal.c
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -1,16 +1,16 @@
 /*
- * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  * Licensed under the GPL
  */
 
 #include <signal.h>
 
-extern void (*handlers[])(int sig, struct sigcontext *sc);
+extern void handle_signal(int sig, struct sigcontext *sc);
 
 void hard_handler(int sig)
 {
 	struct ucontext *uc;
 	asm("movq %%rdx, %0" : "=r" (uc));
 
-	(*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext);
+	handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
 }
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index c307a89..7cbcf48 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -33,25 +33,8 @@
 
 void stack_protections(unsigned long address)
 {
-	int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-
-	if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0)
-		panic("protecting stack failed, errno = %d", errno);
-}
-
-void task_protections(unsigned long address)
-{
-	unsigned long guard = address + UM_KERN_PAGE_SIZE;
-	unsigned long stack = guard + UM_KERN_PAGE_SIZE;
-	int prot = 0, pages;
-
-#ifdef notdef
-	if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0)
-		panic("protecting guard page failed, errno = %d", errno);
-#endif
-	pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2;
-	prot = PROT_READ | PROT_WRITE | PROT_EXEC;
-	if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0)
+	if(mprotect((void *) address, UM_THREAD_SIZE,
+		    PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
 		panic("protecting stack failed, errno = %d", errno);
 }
 
@@ -72,7 +55,7 @@
 
 	/* XXX tcsetattr could have applied only some changes
 	 * (and cfmakeraw() is a set of changes) */
-	return(0);
+	return 0;
 }
 
 void setup_machinename(char *machine_out)
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c
index 92d7d0c..8850fe4 100644
--- a/arch/x86_64/ia32/audit.c
+++ b/arch/x86_64/ia32/audit.c
@@ -20,6 +20,11 @@
 ~0U
 };
 
+unsigned ia32_signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
 int ia32_classify_syscall(unsigned syscall)
 {
 	switch(syscall) {
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index f210683..52be79b 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -716,4 +716,7 @@
 	.quad sys_getcpu
 	.quad sys_epoll_pwait
 	.quad compat_sys_utimensat	/* 320 */
+	.quad sys_signalfd
+	.quad sys_timerfd
+	.quad sys_eventfd
 ia32_syscall_end:		
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index a52af58..a3d450d 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -86,7 +86,7 @@
 		printk("Aperture too small (%d MB)\n", aper_size>>20);
 		return 0;
 	}
-	if (aper_base + aper_size >= 0xffffffff) { 
+	if (aper_base + aper_size > 0x100000000UL) {
 		printk("Aperture beyond 4GB. Ignoring.\n");
 		return 0; 
 	}
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c
index 21f3338..06d3e5a 100644
--- a/arch/x86_64/kernel/audit.c
+++ b/arch/x86_64/kernel/audit.c
@@ -23,6 +23,20 @@
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+#ifdef CONFIG_IA32_EMULATION
+	if (arch == AUDIT_ARCH_I386)
+		return 1;
+#endif
+	return 0;
+}
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 #ifdef CONFIG_IA32_EMULATION
@@ -49,15 +63,18 @@
 	extern __u32 ia32_write_class[];
 	extern __u32 ia32_read_class[];
 	extern __u32 ia32_chattr_class[];
+	extern __u32 ia32_signal_class[];
 	audit_register_class(AUDIT_CLASS_WRITE_32, ia32_write_class);
 	audit_register_class(AUDIT_CLASS_READ_32, ia32_read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL_32, ia32_signal_class);
 #endif
 	audit_register_class(AUDIT_CLASS_WRITE, write_class);
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
diff --git a/arch/x86_64/kernel/bugs.c b/arch/x86_64/kernel/bugs.c
index 12b585b..c141e7a 100644
--- a/arch/x86_64/kernel/bugs.c
+++ b/arch/x86_64/kernel/bugs.c
@@ -13,6 +13,7 @@
 void __init check_bugs(void)
 {
 	identify_cpu(&boot_cpu_data);
+	mtrr_bp_init();
 #if !defined(CONFIG_SMP)
 	printk("CPU: ");
 	print_cpu_info(&boot_cpu_data);
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 213d90e..6c34bdd 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -62,13 +62,6 @@
 {
 	int i;
 
-	/*
-	 * Make sure kernel is aligned to 2MB address. Catching it at compile
-	 * time is better. Change your config file and compile the kernel
-	 * for a 2MB aligned address (CONFIG_PHYSICAL_START)
-	 */
-	BUILD_BUG_ON(CONFIG_PHYSICAL_START & (__KERNEL_ALIGN - 1));
-
 	/* clear bss before set_intr_gate with early_idt_handler */
 	clear_bss();
 
diff --git a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
index 373ef66..ae091cd 100644
--- a/arch/x86_64/kernel/pci-gart.c
+++ b/arch/x86_64/kernel/pci-gart.c
@@ -476,7 +476,7 @@
 	aper_base <<= 25;
 
 	aper_size = (32 * 1024 * 1024) << aper_order; 
-	if (aper_base + aper_size >= 0xffffffff || !aper_size)
+       if (aper_base + aper_size > 0x100000000UL || !aper_size)
 		aper_base = 0;
 
 	*size = aper_size;
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index db51577..eb6524f 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -891,9 +891,7 @@
 #ifdef CONFIG_X86_MCE
 	mcheck_init(c);
 #endif
-	if (c == &boot_cpu_data)
-		mtrr_bp_init();
-	else
+	if (c != &boot_cpu_data)
 		mtrr_ap_init();
 #ifdef CONFIG_NUMA
 	numa_add_cpu(smp_processor_id());
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 8c2ac41..d28f013 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -778,6 +778,7 @@
 			return;
 		if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0)
 								== NOTIFY_STOP)
+			return;
 		if (!do_nmi_callback(regs,cpu))
 			unknown_nmi_error(reason, regs);
 
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c
index 17e1889..74a567a 100644
--- a/block/ll_rw_blk.c
+++ b/block/ll_rw_blk.c
@@ -3116,7 +3116,7 @@
  * bi_sector for remaps as it sees fit.  So the values of these fields
  * should NOT be depended on after the call to generic_make_request.
  */
-void generic_make_request(struct bio *bio)
+static inline void __generic_make_request(struct bio *bio)
 {
 	request_queue_t *q;
 	sector_t maxsector;
@@ -3215,6 +3215,57 @@
 	} while (ret);
 }
 
+/*
+ * We only want one ->make_request_fn to be active at a time,
+ * else stack usage with stacked devices could be a problem.
+ * So use current->bio_{list,tail} to keep a list of requests
+ * submited by a make_request_fn function.
+ * current->bio_tail is also used as a flag to say if
+ * generic_make_request is currently active in this task or not.
+ * If it is NULL, then no make_request is active.  If it is non-NULL,
+ * then a make_request is active, and new requests should be added
+ * at the tail
+ */
+void generic_make_request(struct bio *bio)
+{
+	if (current->bio_tail) {
+		/* make_request is active */
+		*(current->bio_tail) = bio;
+		bio->bi_next = NULL;
+		current->bio_tail = &bio->bi_next;
+		return;
+	}
+	/* following loop may be a bit non-obvious, and so deserves some
+	 * explanation.
+	 * Before entering the loop, bio->bi_next is NULL (as all callers
+	 * ensure that) so we have a list with a single bio.
+	 * We pretend that we have just taken it off a longer list, so
+	 * we assign bio_list to the next (which is NULL) and bio_tail
+	 * to &bio_list, thus initialising the bio_list of new bios to be
+	 * added.  __generic_make_request may indeed add some more bios
+	 * through a recursive call to generic_make_request.  If it
+	 * did, we find a non-NULL value in bio_list and re-enter the loop
+	 * from the top.  In this case we really did just take the bio
+	 * of the top of the list (no pretending) and so fixup bio_list and
+	 * bio_tail or bi_next, and call into __generic_make_request again.
+	 *
+	 * The loop was structured like this to make only one call to
+	 * __generic_make_request (which is important as it is large and
+	 * inlined) and to keep the structure simple.
+	 */
+	BUG_ON(bio->bi_next);
+	do {
+		current->bio_list = bio->bi_next;
+		if (bio->bi_next == NULL)
+			current->bio_tail = &current->bio_list;
+		else
+			bio->bi_next = NULL;
+		__generic_make_request(bio);
+		bio = current->bio_list;
+	} while (bio);
+	current->bio_tail = NULL; /* deactivate */
+}
+
 EXPORT_SYMBOL(generic_make_request);
 
 /**
diff --git a/drivers/Makefile b/drivers/Makefile
index 26ca903..adad2f3 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -36,6 +36,7 @@
 obj-$(CONFIG_SCSI)		+= scsi/
 obj-$(CONFIG_ATA)		+= ata/
 obj-$(CONFIG_FUSION)		+= message/
+obj-$(CONFIG_FIREWIRE)		+= firewire/
 obj-$(CONFIG_IEEE1394)		+= ieee1394/
 obj-y				+= cdrom/
 obj-y				+= auxdisplay/
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
index 1683e5c..1cbe619 100644
--- a/drivers/acpi/dispatcher/dsmethod.c
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -231,8 +231,10 @@
 		 * Obtain the method mutex if necessary. Do not acquire mutex for a
 		 * recursive call.
 		 */
-		if (acpi_os_get_thread_id() !=
-		    obj_desc->method.mutex->mutex.owner_thread_id) {
+		if (!walk_state ||
+		    !obj_desc->method.mutex->mutex.owner_thread ||
+		    (walk_state->thread !=
+		     obj_desc->method.mutex->mutex.owner_thread)) {
 			/*
 			 * Acquire the method mutex. This releases the interpreter if we
 			 * block (and reacquires it before it returns)
@@ -246,14 +248,14 @@
 			}
 
 			/* Update the mutex and walk info and save the original sync_level */
-			obj_desc->method.mutex->mutex.owner_thread_id =
-				acpi_os_get_thread_id();
 
 			if (walk_state) {
 				obj_desc->method.mutex->mutex.
 				    original_sync_level =
 				    walk_state->thread->current_sync_level;
 
+				obj_desc->method.mutex->mutex.owner_thread =
+				    walk_state->thread;
 				walk_state->thread->current_sync_level =
 				    obj_desc->method.sync_level;
 			} else {
@@ -567,7 +569,7 @@
 
 			acpi_os_release_mutex(method_desc->method.mutex->mutex.
 					      os_mutex);
-			method_desc->method.mutex->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+			method_desc->method.mutex->mutex.owner_thread = NULL;
 		}
 	}
 
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 6c6104a..fc9da48 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -866,8 +866,7 @@
 		    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
 		     (op->common.parent->common.aml_opcode !=
 		      AML_VAR_PACKAGE_OP)
-		     && (op->common.parent->common.aml_opcode !=
-			 AML_NAME_OP))) {
+		     && (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
 			walk_state->result_obj = obj_desc;
 		}
 	}
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
index e4073e0..71503c0 100644
--- a/drivers/acpi/dispatcher/dsutils.c
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -556,10 +556,9 @@
 					 * indicate this to the interpreter, set the
 					 * object to the root
 					 */
-					obj_desc =
-					    ACPI_CAST_PTR(union
-							  acpi_operand_object,
-							  acpi_gbl_root_node);
+					obj_desc = ACPI_CAST_PTR(union
+								 acpi_operand_object,
+								 acpi_gbl_root_node);
 					status = AE_OK;
 				} else {
 					/*
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
index 16c8e38..5afcdd9 100644
--- a/drivers/acpi/dispatcher/dswstate.c
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -630,12 +630,9 @@
  *
  ******************************************************************************/
 
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
-						  union acpi_parse_object
-						  *origin,
-						  union acpi_operand_object
-						  *method_desc,
-						  struct acpi_thread_state
+struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
+						  *origin, union acpi_operand_object
+						  *method_desc, struct acpi_thread_state
 						  *thread)
 {
 	struct acpi_walk_state *walk_state;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e08cf98..82f496c 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -147,9 +147,10 @@
 	return 0;
 }
 
-static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
+static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event,
+                        unsigned count, int force_poll)
 {
-	if (acpi_ec_mode == EC_POLL) {
+	if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) {
 		unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
 		while (time_before(jiffies, delay)) {
 			if (acpi_ec_check_status(ec, event, 0))
@@ -173,14 +174,15 @@
 
 static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
 					const u8 * wdata, unsigned wdata_len,
-					u8 * rdata, unsigned rdata_len)
+					u8 * rdata, unsigned rdata_len,
+					int force_poll)
 {
 	int result = 0;
 	unsigned count = atomic_read(&ec->event_count);
 	acpi_ec_write_cmd(ec, command);
 
 	for (; wdata_len > 0; --wdata_len) {
-		result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
+		result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
 		if (result) {
 			printk(KERN_ERR PREFIX
 			       "write_cmd timeout, command = %d\n", command);
@@ -191,7 +193,7 @@
 	}
 
 	if (!rdata_len) {
-		result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count);
+		result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
 		if (result) {
 			printk(KERN_ERR PREFIX
 			       "finish-write timeout, command = %d\n", command);
@@ -202,7 +204,7 @@
 	}
 
 	for (; rdata_len > 0; --rdata_len) {
-		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count);
+		result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll);
 		if (result) {
 			printk(KERN_ERR PREFIX "read timeout, command = %d\n",
 			       command);
@@ -217,7 +219,8 @@
 
 static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
 			       const u8 * wdata, unsigned wdata_len,
-			       u8 * rdata, unsigned rdata_len)
+			       u8 * rdata, unsigned rdata_len,
+			       int force_poll)
 {
 	int status;
 	u32 glk;
@@ -240,7 +243,7 @@
 	/* Make sure GPE is enabled before doing transaction */
 	acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
 
-	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
+	status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
 	if (status) {
 		printk(KERN_DEBUG PREFIX
 		       "input buffer is not empty, aborting transaction\n");
@@ -249,7 +252,8 @@
 
 	status = acpi_ec_transaction_unlocked(ec, command,
 					      wdata, wdata_len,
-					      rdata, rdata_len);
+					      rdata, rdata_len,
+					      force_poll);
 
       end:
 
@@ -267,12 +271,12 @@
 int acpi_ec_burst_enable(struct acpi_ec *ec)
 {
 	u8 d;
-	return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1);
+	return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0);
 }
 
 int acpi_ec_burst_disable(struct acpi_ec *ec)
 {
-	return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0);
+	return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0);
 }
 
 static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
@@ -281,7 +285,7 @@
 	u8 d;
 
 	result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
-				     &address, 1, &d, 1);
+				     &address, 1, &d, 1, 0);
 	*data = d;
 	return result;
 }
@@ -290,7 +294,7 @@
 {
 	u8 wdata[2] = { address, data };
 	return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
-				   wdata, 2, NULL, 0);
+				   wdata, 2, NULL, 0, 0);
 }
 
 /*
@@ -349,13 +353,15 @@
 
 int ec_transaction(u8 command,
 		   const u8 * wdata, unsigned wdata_len,
-		   u8 * rdata, unsigned rdata_len)
+		   u8 * rdata, unsigned rdata_len,
+		   int force_poll)
 {
 	if (!first_ec)
 		return -ENODEV;
 
 	return acpi_ec_transaction(first_ec, command, wdata,
-				   wdata_len, rdata, rdata_len);
+				   wdata_len, rdata, rdata_len,
+				   force_poll);
 }
 
 EXPORT_SYMBOL(ec_transaction);
@@ -374,7 +380,7 @@
 	 * bit to be cleared (and thus clearing the interrupt source).
 	 */
 
-	result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1);
+	result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0);
 	if (result)
 		return result;
 
@@ -410,6 +416,7 @@
 	acpi_status status = AE_OK;
 	u8 value;
 	struct acpi_ec *ec = data;
+
 	atomic_inc(&ec->event_count);
 
 	if (acpi_ec_mode == EC_INTR) {
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 635ba44..e22f4a9 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -341,9 +341,8 @@
 
 	/* A Non-NULL gpe_device means this is a GPE Block Device */
 
-	obj_desc =
-	    acpi_ns_get_attached_object((struct acpi_namespace_node *)
-					gpe_device);
+	obj_desc = acpi_ns_get_attached_object((struct acpi_namespace_node *)
+					       gpe_device);
 	if (!obj_desc || !obj_desc->device.gpe_block) {
 		return (NULL);
 	}
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c
index ad5bc76..902c287 100644
--- a/drivers/acpi/events/evgpeblk.c
+++ b/drivers/acpi/events/evgpeblk.c
@@ -1033,8 +1033,7 @@
 
 			if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
 			     ACPI_GPE_DISPATCH_METHOD)
-			    && (gpe_event_info->
-				flags & ACPI_GPE_TYPE_RUNTIME)) {
+			    && (gpe_event_info->flags & ACPI_GPE_TYPE_RUNTIME)) {
 				gpe_enabled_count++;
 			}
 
diff --git a/drivers/acpi/events/evmisc.c b/drivers/acpi/events/evmisc.c
index cae786c..21cb749 100644
--- a/drivers/acpi/events/evmisc.c
+++ b/drivers/acpi/events/evmisc.c
@@ -196,15 +196,12 @@
 		notify_info->notify.value = (u16) notify_value;
 		notify_info->notify.handler_obj = handler_obj;
 
-		acpi_ex_exit_interpreter();
-
-		acpi_ev_notify_dispatch(notify_info);
-
-		status = acpi_ex_enter_interpreter();
+		status =
+		    acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
+				    notify_info);
 		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
+			acpi_ut_delete_generic_state(notify_info);
 		}
-
 	}
 
 	if (!handler_obj) {
@@ -323,8 +320,9 @@
 		acpi_gbl_global_lock_acquired = TRUE;
 		/* Send a unit to the semaphore */
 
-		if (ACPI_FAILURE(acpi_os_signal_semaphore(
-			acpi_gbl_global_lock_semaphore, 1))) {
+		if (ACPI_FAILURE
+		    (acpi_os_signal_semaphore
+		     (acpi_gbl_global_lock_semaphore, 1))) {
 			ACPI_ERROR((AE_INFO,
 				    "Could not signal Global Lock semaphore"));
 		}
@@ -450,7 +448,9 @@
 	}
 
 	if (ACPI_FAILURE(status)) {
-		status = acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex, timeout);
+		status =
+		    acpi_ex_system_wait_mutex(acpi_gbl_global_lock_mutex,
+					      timeout);
 	}
 	if (ACPI_FAILURE(status)) {
 		return_ACPI_STATUS(status);
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c
index 96b0e84..e99f0c4 100644
--- a/drivers/acpi/events/evregion.c
+++ b/drivers/acpi/events/evregion.c
@@ -291,7 +291,6 @@
 			       u32 bit_width, acpi_integer * value)
 {
 	acpi_status status;
-	acpi_status status2;
 	acpi_adr_space_handler handler;
 	acpi_adr_space_setup region_setup;
 	union acpi_operand_object *handler_desc;
@@ -345,7 +344,7 @@
 		 * setup will potentially execute control methods
 		 * (e.g., _REG method for this region)
 		 */
-		acpi_ex_exit_interpreter();
+		acpi_ex_relinquish_interpreter();
 
 		status = region_setup(region_obj, ACPI_REGION_ACTIVATE,
 				      handler_desc->address_space.context,
@@ -353,10 +352,7 @@
 
 		/* Re-enter the interpreter */
 
-		status2 = acpi_ex_enter_interpreter();
-		if (ACPI_FAILURE(status2)) {
-			return_ACPI_STATUS(status2);
-		}
+		acpi_ex_reacquire_interpreter();
 
 		/* Check for failure of the Region Setup */
 
@@ -409,7 +405,7 @@
 		 * exit the interpreter because the handler *might* block -- we don't
 		 * know what it will do, so we can't hold the lock on the intepreter.
 		 */
-		acpi_ex_exit_interpreter();
+		acpi_ex_relinquish_interpreter();
 	}
 
 	/* Call the handler */
@@ -430,10 +426,7 @@
 		 * We just returned from a non-default handler, we must re-enter the
 		 * interpreter
 		 */
-		status2 = acpi_ex_enter_interpreter();
-		if (ACPI_FAILURE(status2)) {
-			return_ACPI_STATUS(status2);
-		}
+		acpi_ex_reacquire_interpreter();
 	}
 
 	return_ACPI_STATUS(status);
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c
index a4fa7e6..400d90f 100644
--- a/drivers/acpi/events/evrgnini.c
+++ b/drivers/acpi/events/evrgnini.c
@@ -228,7 +228,8 @@
 
 				/* Install a handler for this PCI root bridge */
 
-				status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
+				status =
+				    acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
 				if (ACPI_FAILURE(status)) {
 					if (status == AE_SAME_HANDLER) {
 						/*
diff --git a/drivers/acpi/events/evxface.c b/drivers/acpi/events/evxface.c
index a3379ba..6d866a0 100644
--- a/drivers/acpi/events/evxface.c
+++ b/drivers/acpi/events/evxface.c
@@ -91,7 +91,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
 #endif				/*  ACPI_FUTURE_USAGE  */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_fixed_event_handler
@@ -768,11 +767,9 @@
 		return (AE_BAD_PARAMETER);
 	}
 
-	status = acpi_ex_enter_interpreter();
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
+	/* Must lock interpreter to prevent race conditions */
 
+	acpi_ex_enter_interpreter();
 	status = acpi_ev_acquire_global_lock(timeout);
 	acpi_ex_exit_interpreter();
 
diff --git a/drivers/acpi/events/evxfevnt.c b/drivers/acpi/events/evxfevnt.c
index 17065e9..9cbd341 100644
--- a/drivers/acpi/events/evxfevnt.c
+++ b/drivers/acpi/events/evxfevnt.c
@@ -472,7 +472,6 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
-
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -568,7 +567,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
 #endif				/*  ACPI_FUTURE_USAGE  */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_install_gpe_block
diff --git a/drivers/acpi/executer/exconvrt.c b/drivers/acpi/executer/exconvrt.c
index d470e8b..79f2c0d 100644
--- a/drivers/acpi/executer/exconvrt.c
+++ b/drivers/acpi/executer/exconvrt.c
@@ -512,9 +512,8 @@
 		 * Create a new string object and string buffer
 		 * (-1 because of extra separator included in string_length from above)
 		 */
-		return_desc =
-		    acpi_ut_create_string_object((acpi_size)
-						 (string_length - 1));
+		return_desc = acpi_ut_create_string_object((acpi_size)
+							   (string_length - 1));
 		if (!return_desc) {
 			return_ACPI_STATUS(AE_NO_MEMORY);
 		}
diff --git a/drivers/acpi/executer/excreate.c b/drivers/acpi/executer/excreate.c
index ae97812..6e9a23e 100644
--- a/drivers/acpi/executer/excreate.c
+++ b/drivers/acpi/executer/excreate.c
@@ -50,7 +50,6 @@
 
 #define _COMPONENT          ACPI_EXECUTER
 ACPI_MODULE_NAME("excreate")
-
 #ifndef ACPI_NO_METHOD_EXECUTION
 /*******************************************************************************
  *
@@ -583,10 +582,7 @@
 	 * Get the sync_level. If method is serialized, a mutex will be
 	 * created for this method when it is parsed.
 	 */
-	if (acpi_gbl_all_methods_serialized) {
-		obj_desc->method.sync_level = 0;
-		obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
-	} else if (method_flags & AML_METHOD_SERIALIZED) {
+	if (method_flags & AML_METHOD_SERIALIZED) {
 		/*
 		 * ACPI 1.0: sync_level = 0
 		 * ACPI 2.0: sync_level = sync_level in method declaration
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index 1a73c14..51c9c29 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -134,7 +134,7 @@
 static struct acpi_exdump_info acpi_ex_dump_mutex[5] = {
 	{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_mutex), NULL},
 	{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(mutex.sync_level), "Sync Level"},
-	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread_id), "Owner Thread"},
+	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.owner_thread), "Owner Thread"},
 	{ACPI_EXD_UINT16, ACPI_EXD_OFFSET(mutex.acquisition_depth),
 	 "Acquire Depth"},
 	{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(mutex.os_mutex), "OsMutex"}
@@ -451,9 +451,8 @@
 
 	ACPI_FUNCTION_NAME(ex_dump_operand)
 
-	    if (!
-		((ACPI_LV_EXEC & acpi_dbg_level)
-		 && (_COMPONENT & acpi_dbg_layer))) {
+	    if (!((ACPI_LV_EXEC & acpi_dbg_level)
+		  && (_COMPONENT & acpi_dbg_layer))) {
 		return;
 	}
 
@@ -844,9 +843,8 @@
 	ACPI_FUNCTION_ENTRY();
 
 	if (!flags) {
-		if (!
-		    ((ACPI_LV_OBJECTS & acpi_dbg_level)
-		     && (_COMPONENT & acpi_dbg_layer))) {
+		if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+		      && (_COMPONENT & acpi_dbg_layer))) {
 			return;
 		}
 	}
@@ -1011,9 +1009,8 @@
 	}
 
 	if (!flags) {
-		if (!
-		    ((ACPI_LV_OBJECTS & acpi_dbg_level)
-		     && (_COMPONENT & acpi_dbg_layer))) {
+		if (!((ACPI_LV_OBJECTS & acpi_dbg_level)
+		      && (_COMPONENT & acpi_dbg_layer))) {
 			return_VOID;
 		}
 	}
diff --git a/drivers/acpi/executer/exmutex.c b/drivers/acpi/executer/exmutex.c
index 4eb883b..6748e3e 100644
--- a/drivers/acpi/executer/exmutex.c
+++ b/drivers/acpi/executer/exmutex.c
@@ -66,9 +66,10 @@
  *
  ******************************************************************************/
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
-			  struct acpi_thread_state *thread)
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc)
 {
+	struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
+
 	if (!thread) {
 		return;
 	}
@@ -173,13 +174,16 @@
 
 	/* Support for multiple acquires by the owning thread */
 
-	if (obj_desc->mutex.owner_thread_id == acpi_os_get_thread_id()) {
-		/*
-		 * The mutex is already owned by this thread, just increment the
-		 * acquisition depth
-		 */
-		obj_desc->mutex.acquisition_depth++;
-		return_ACPI_STATUS(AE_OK);
+	if (obj_desc->mutex.owner_thread) {
+		if (obj_desc->mutex.owner_thread->thread_id ==
+		    walk_state->thread->thread_id) {
+			/*
+			 * The mutex is already owned by this thread, just increment the
+			 * acquisition depth
+			 */
+			obj_desc->mutex.acquisition_depth++;
+			return_ACPI_STATUS(AE_OK);
+		}
 	}
 
 	/* Acquire the mutex, wait if necessary. Special case for Global Lock */
@@ -202,7 +206,7 @@
 
 	/* Have the mutex: update mutex and walk info and save the sync_level */
 
-	obj_desc->mutex.owner_thread_id = acpi_os_get_thread_id();
+	obj_desc->mutex.owner_thread = walk_state->thread;
 	obj_desc->mutex.acquisition_depth = 1;
 	obj_desc->mutex.original_sync_level =
 	    walk_state->thread->current_sync_level;
@@ -242,7 +246,7 @@
 
 	/* The mutex must have been previously acquired in order to release it */
 
-	if (!obj_desc->mutex.owner_thread_id) {
+	if (!obj_desc->mutex.owner_thread) {
 		ACPI_ERROR((AE_INFO,
 			    "Cannot release Mutex [%4.4s], not acquired",
 			    acpi_ut_get_node_name(obj_desc->mutex.node)));
@@ -262,14 +266,15 @@
 	 * The Mutex is owned, but this thread must be the owner.
 	 * Special case for Global Lock, any thread can release
 	 */
-	if ((obj_desc->mutex.owner_thread_id !=
+	if ((obj_desc->mutex.owner_thread->thread_id !=
 	     walk_state->thread->thread_id)
 	    && (obj_desc->mutex.os_mutex != acpi_gbl_global_lock_mutex)) {
 		ACPI_ERROR((AE_INFO,
 			    "Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
 			    (unsigned long)walk_state->thread->thread_id,
 			    acpi_ut_get_node_name(obj_desc->mutex.node),
-			    (unsigned long)obj_desc->mutex.owner_thread_id));
+			    (unsigned long)obj_desc->mutex.owner_thread->
+			    thread_id));
 		return_ACPI_STATUS(AE_AML_NOT_OWNER);
 	}
 
@@ -296,7 +301,7 @@
 
 	/* Unlink the mutex from the owner's list */
 
-	acpi_ex_unlink_mutex(obj_desc, walk_state->thread);
+	acpi_ex_unlink_mutex(obj_desc);
 
 	/* Release the mutex, special case for Global Lock */
 
@@ -308,7 +313,7 @@
 
 	/* Update the mutex and restore sync_level */
 
-	obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+	obj_desc->mutex.owner_thread = NULL;
 	walk_state->thread->current_sync_level =
 	    obj_desc->mutex.original_sync_level;
 
@@ -363,7 +368,7 @@
 
 		/* Mark mutex unowned */
 
-		obj_desc->mutex.owner_thread_id = ACPI_MUTEX_NOT_ACQUIRED;
+		obj_desc->mutex.owner_thread = NULL;
 
 		/* Update Thread sync_level (Last mutex is the important one) */
 
diff --git a/drivers/acpi/executer/exnames.c b/drivers/acpi/executer/exnames.c
index 1ee4fb1..308eae5 100644
--- a/drivers/acpi/executer/exnames.c
+++ b/drivers/acpi/executer/exnames.c
@@ -177,8 +177,7 @@
 
 	ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Bytes from stream:\n"));
 
-	for (index = 0;
-	     (index < ACPI_NAME_SIZE)
+	for (index = 0; (index < ACPI_NAME_SIZE)
 	     && (acpi_ut_valid_acpi_char(*aml_address, 0)); index++) {
 		char_buf[index] = *aml_address++;
 		ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "%c\n", char_buf[index]));
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index a669662..efe5d4b 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -242,7 +242,7 @@
 					    obj_desc->common_field.bit_length,
 					    0xFFFFFFFF
 					    /* Temp until we pass region_length as parameter */
-					    );
+		    );
 		bit_length = byte_alignment * 8;
 #endif
 
diff --git a/drivers/acpi/executer/exresop.c b/drivers/acpi/executer/exresop.c
index ba76186..09d897b 100644
--- a/drivers/acpi/executer/exresop.c
+++ b/drivers/acpi/executer/exresop.c
@@ -354,8 +354,7 @@
 			if ((opcode == AML_STORE_OP) &&
 			    (ACPI_GET_OBJECT_TYPE(*stack_ptr) ==
 			     ACPI_TYPE_LOCAL_REFERENCE)
-			    && ((*stack_ptr)->reference.opcode ==
-				AML_INDEX_OP)) {
+			    && ((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
 				goto next_operand;
 			}
 			break;
diff --git a/drivers/acpi/executer/exsystem.c b/drivers/acpi/executer/exsystem.c
index b2edf62..9460baf 100644
--- a/drivers/acpi/executer/exsystem.c
+++ b/drivers/acpi/executer/exsystem.c
@@ -66,7 +66,6 @@
 acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout)
 {
 	acpi_status status;
-	acpi_status status2;
 
 	ACPI_FUNCTION_TRACE(ex_system_wait_semaphore);
 
@@ -79,7 +78,7 @@
 
 		/* We must wait, so unlock the interpreter */
 
-		acpi_ex_exit_interpreter();
+		acpi_ex_relinquish_interpreter();
 
 		status = acpi_os_wait_semaphore(semaphore, 1, timeout);
 
@@ -89,13 +88,7 @@
 
 		/* Reacquire the interpreter */
 
-		status2 = acpi_ex_enter_interpreter();
-		if (ACPI_FAILURE(status2)) {
-
-			/* Report fatal error, could not acquire interpreter */
-
-			return_ACPI_STATUS(status2);
-		}
+		acpi_ex_reacquire_interpreter();
 	}
 
 	return_ACPI_STATUS(status);
@@ -119,7 +112,6 @@
 acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout)
 {
 	acpi_status status;
-	acpi_status status2;
 
 	ACPI_FUNCTION_TRACE(ex_system_wait_mutex);
 
@@ -132,7 +124,7 @@
 
 		/* We must wait, so unlock the interpreter */
 
-		acpi_ex_exit_interpreter();
+		acpi_ex_relinquish_interpreter();
 
 		status = acpi_os_acquire_mutex(mutex, timeout);
 
@@ -142,13 +134,7 @@
 
 		/* Reacquire the interpreter */
 
-		status2 = acpi_ex_enter_interpreter();
-		if (ACPI_FAILURE(status2)) {
-
-			/* Report fatal error, could not acquire interpreter */
-
-			return_ACPI_STATUS(status2);
-		}
+		acpi_ex_reacquire_interpreter();
 	}
 
 	return_ACPI_STATUS(status);
@@ -209,20 +195,18 @@
 
 acpi_status acpi_ex_system_do_suspend(acpi_integer how_long)
 {
-	acpi_status status;
-
 	ACPI_FUNCTION_ENTRY();
 
 	/* Since this thread will sleep, we must release the interpreter */
 
-	acpi_ex_exit_interpreter();
+	acpi_ex_relinquish_interpreter();
 
 	acpi_os_sleep(how_long);
 
 	/* And now we must get the interpreter again */
 
-	status = acpi_ex_enter_interpreter();
-	return (status);
+	acpi_ex_reacquire_interpreter();
+	return (AE_OK);
 }
 
 /*******************************************************************************
diff --git a/drivers/acpi/executer/exutils.c b/drivers/acpi/executer/exutils.c
index aea461f..6b0aecc 100644
--- a/drivers/acpi/executer/exutils.c
+++ b/drivers/acpi/executer/exutils.c
@@ -76,14 +76,15 @@
  *
  * PARAMETERS:  None
  *
- * RETURN:      Status
+ * RETURN:      None
  *
- * DESCRIPTION: Enter the interpreter execution region.  Failure to enter
- *              the interpreter region is a fatal system error
+ * DESCRIPTION: Enter the interpreter execution region. Failure to enter
+ *              the interpreter region is a fatal system error. Used in
+ *              conjunction with exit_interpreter.
  *
  ******************************************************************************/
 
-acpi_status acpi_ex_enter_interpreter(void)
+void acpi_ex_enter_interpreter(void)
 {
 	acpi_status status;
 
@@ -91,10 +92,42 @@
 
 	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
 	if (ACPI_FAILURE(status)) {
-		ACPI_ERROR((AE_INFO, "Could not acquire interpreter mutex"));
+		ACPI_ERROR((AE_INFO,
+			    "Could not acquire AML Interpreter mutex"));
 	}
 
-	return_ACPI_STATUS(status);
+	return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_reacquire_interpreter
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Reacquire the interpreter execution region from within the
+ *              interpreter code. Failure to enter the interpreter region is a
+ *              fatal system error. Used in  conjuction with
+ *              relinquish_interpreter
+ *
+ ******************************************************************************/
+
+void acpi_ex_reacquire_interpreter(void)
+{
+	ACPI_FUNCTION_TRACE(ex_reacquire_interpreter);
+
+	/*
+	 * If the global serialized flag is set, do not release the interpreter,
+	 * since it was not actually released by acpi_ex_relinquish_interpreter.
+	 * This forces the interpreter to be single threaded.
+	 */
+	if (!acpi_gbl_all_methods_serialized) {
+		acpi_ex_enter_interpreter();
+	}
+
+	return_VOID;
 }
 
 /*******************************************************************************
@@ -105,17 +138,9 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Exit the interpreter execution region
- *
- * Cases where the interpreter is unlocked:
- *      1) Completion of the execution of a control method
- *      2) Method blocked on a Sleep() AML opcode
- *      3) Method blocked on an Acquire() AML opcode
- *      4) Method blocked on a Wait() AML opcode
- *      5) Method blocked to acquire the global lock
- *      6) Method blocked to execute a serialized control method that is
- *          already executing
- *      7) About to invoke a user-installed opregion handler
+ * DESCRIPTION: Exit the interpreter execution region. This is the top level
+ *              routine used to exit the interpreter when all processing has
+ *              been completed.
  *
  ******************************************************************************/
 
@@ -127,7 +152,46 @@
 
 	status = acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
 	if (ACPI_FAILURE(status)) {
-		ACPI_ERROR((AE_INFO, "Could not release interpreter mutex"));
+		ACPI_ERROR((AE_INFO,
+			    "Could not release AML Interpreter mutex"));
+	}
+
+	return_VOID;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ex_relinquish_interpreter
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Exit the interpreter execution region, from within the
+ *              interpreter - before attempting an operation that will possibly
+ *              block the running thread.
+ *
+ * Cases where the interpreter is unlocked internally
+ *      1) Method to be blocked on a Sleep() AML opcode
+ *      2) Method to be blocked on an Acquire() AML opcode
+ *      3) Method to be blocked on a Wait() AML opcode
+ *      4) Method to be blocked to acquire the global lock
+ *      5) Method to be blocked waiting to execute a serialized control method
+ *          that is currently executing
+ *      6) About to invoke a user-installed opregion handler
+ *
+ ******************************************************************************/
+
+void acpi_ex_relinquish_interpreter(void)
+{
+	ACPI_FUNCTION_TRACE(ex_relinquish_interpreter);
+
+	/*
+	 * If the global serialized flag is set, do not release the interpreter.
+	 * This forces the interpreter to be single threaded.
+	 */
+	if (!acpi_gbl_all_methods_serialized) {
+		acpi_ex_exit_interpreter();
 	}
 
 	return_VOID;
@@ -141,8 +205,8 @@
  *
  * RETURN:      none
  *
- * DESCRIPTION: Truncate a number to 32-bits if the currently executing method
- *              belongs to a 32-bit ACPI table.
+ * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is
+ *              32-bit, as determined by the revision of the DSDT.
  *
  ******************************************************************************/
 
diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
index c84b1fa..76c525d 100644
--- a/drivers/acpi/hardware/hwsleep.c
+++ b/drivers/acpi/hardware/hwsleep.c
@@ -152,7 +152,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)
 #endif
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_enter_sleep_state_prep
diff --git a/drivers/acpi/namespace/nseval.c b/drivers/acpi/namespace/nseval.c
index 26fd0dd..97b2ac5 100644
--- a/drivers/acpi/namespace/nseval.c
+++ b/drivers/acpi/namespace/nseval.c
@@ -75,7 +75,7 @@
  * MUTEX:       Locks interpreter
  *
  ******************************************************************************/
-acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info)
+acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
 {
 	acpi_status status;
 
@@ -154,11 +154,7 @@
 		 * Execute the method via the interpreter. The interpreter is locked
 		 * here before calling into the AML parser
 		 */
-		status = acpi_ex_enter_interpreter();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
-
+		acpi_ex_enter_interpreter();
 		status = acpi_ps_execute_method(info);
 		acpi_ex_exit_interpreter();
 	} else {
@@ -182,10 +178,7 @@
 		 * resolution, we must lock it because we could access an opregion.
 		 * The opregion access code assumes that the interpreter is locked.
 		 */
-		status = acpi_ex_enter_interpreter();
-		if (ACPI_FAILURE(status)) {
-			return_ACPI_STATUS(status);
-		}
+		acpi_ex_enter_interpreter();
 
 		/* Function has a strange interface */
 
diff --git a/drivers/acpi/namespace/nsinit.c b/drivers/acpi/namespace/nsinit.c
index c4ab615..33db224 100644
--- a/drivers/acpi/namespace/nsinit.c
+++ b/drivers/acpi/namespace/nsinit.c
@@ -214,7 +214,7 @@
 			u32 level, void *context, void **return_value)
 {
 	acpi_object_type type;
-	acpi_status status;
+	acpi_status status = AE_OK;
 	struct acpi_init_walk_info *info =
 	    (struct acpi_init_walk_info *)context;
 	struct acpi_namespace_node *node =
@@ -268,10 +268,7 @@
 	/*
 	 * Must lock the interpreter before executing AML code
 	 */
-	status = acpi_ex_enter_interpreter();
-	if (ACPI_FAILURE(status)) {
-		return (status);
-	}
+	acpi_ex_enter_interpreter();
 
 	/*
 	 * Each of these types can contain executable AML code within the
diff --git a/drivers/acpi/namespace/nswalk.c b/drivers/acpi/namespace/nswalk.c
index 94eb8f3..280b835 100644
--- a/drivers/acpi/namespace/nswalk.c
+++ b/drivers/acpi/namespace/nswalk.c
@@ -65,10 +65,8 @@
  *              within Scope is returned.
  *
  ******************************************************************************/
-struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
-						  struct acpi_namespace_node
-						  *parent_node,
-						  struct acpi_namespace_node
+struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct acpi_namespace_node
+						  *parent_node, struct acpi_namespace_node
 						  *child_node)
 {
 	struct acpi_namespace_node *next_node = NULL;
diff --git a/drivers/acpi/namespace/nsxfeval.c b/drivers/acpi/namespace/nsxfeval.c
index 8904d0f..be4f289 100644
--- a/drivers/acpi/namespace/nsxfeval.c
+++ b/drivers/acpi/namespace/nsxfeval.c
@@ -48,7 +48,6 @@
 
 #define _COMPONENT          ACPI_NAMESPACE
 ACPI_MODULE_NAME("nsxfeval")
-
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -73,8 +72,8 @@
 acpi_status
 acpi_evaluate_object_typed(acpi_handle handle,
 			   acpi_string pathname,
-			   struct acpi_object_list * external_params,
-			   struct acpi_buffer * return_buffer,
+			   struct acpi_object_list *external_params,
+			   struct acpi_buffer *return_buffer,
 			   acpi_object_type return_type)
 {
 	acpi_status status;
@@ -143,7 +142,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed)
 #endif				/*  ACPI_FUTURE_USAGE  */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_evaluate_object
@@ -170,7 +168,6 @@
 		     struct acpi_buffer *return_buffer)
 {
 	acpi_status status;
-	acpi_status status2;
 	struct acpi_evaluate_info *info;
 	acpi_size buffer_space_needed;
 	u32 i;
@@ -329,14 +326,12 @@
 		 * Delete the internal return object. NOTE: Interpreter must be
 		 * locked to avoid race condition.
 		 */
-		status2 = acpi_ex_enter_interpreter();
-		if (ACPI_SUCCESS(status2)) {
+		acpi_ex_enter_interpreter();
 
-			/* Remove one reference on the return object (should delete it) */
+		/* Remove one reference on the return object (should delete it) */
 
-			acpi_ut_remove_reference(info->return_object);
-			acpi_ex_exit_interpreter();
-		}
+		acpi_ut_remove_reference(info->return_object);
+		acpi_ex_exit_interpreter();
 	}
 
       cleanup:
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c2bed56..b998340 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -71,6 +71,7 @@
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
+static struct workqueue_struct *kacpi_notify_wq;
 
 static void __init acpi_request_region (struct acpi_generic_address *addr,
 	unsigned int length, char *desc)
@@ -137,8 +138,9 @@
 		return AE_NULL_ENTRY;
 	}
 	kacpid_wq = create_singlethread_workqueue("kacpid");
+	kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify");
 	BUG_ON(!kacpid_wq);
-
+	BUG_ON(!kacpi_notify_wq);
 	return AE_OK;
 }
 
@@ -150,6 +152,7 @@
 	}
 
 	destroy_workqueue(kacpid_wq);
+	destroy_workqueue(kacpi_notify_wq);
 
 	return AE_OK;
 }
@@ -603,6 +606,23 @@
 static void acpi_os_execute_deferred(struct work_struct *work)
 {
 	struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
+	if (!dpc) {
+		printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
+		return;
+	}
+
+	dpc->function(dpc->context);
+	kfree(dpc);
+
+	/* Yield cpu to notify thread */
+	cond_resched();
+
+	return;
+}
+
+static void acpi_os_execute_notify(struct work_struct *work)
+{
+	struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
 
 	if (!dpc) {
 		printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
@@ -637,14 +657,12 @@
 	acpi_status status = AE_OK;
 	struct acpi_os_dpc *dpc;
 
-	ACPI_FUNCTION_TRACE("os_queue_for_execution");
-
 	ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 			  "Scheduling function [%p(%p)] for deferred execution.\n",
 			  function, context));
 
 	if (!function)
-		return_ACPI_STATUS(AE_BAD_PARAMETER);
+		return AE_BAD_PARAMETER;
 
 	/*
 	 * Allocate/initialize DPC structure.  Note that this memory will be
@@ -662,14 +680,21 @@
 	dpc->function = function;
 	dpc->context = context;
 
-	INIT_WORK(&dpc->work, acpi_os_execute_deferred);
-	if (!queue_work(kacpid_wq, &dpc->work)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+	if (type == OSL_NOTIFY_HANDLER) {
+		INIT_WORK(&dpc->work, acpi_os_execute_notify);
+		if (!queue_work(kacpi_notify_wq, &dpc->work)) {
+			status = AE_ERROR;
+			kfree(dpc);
+		}
+	} else {
+		INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+		if (!queue_work(kacpid_wq, &dpc->work)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
 				  "Call to queue_work() failed.\n"));
-		kfree(dpc);
-		status = AE_ERROR;
+			status = AE_ERROR;
+			kfree(dpc);
+		}
 	}
-
 	return_ACPI_STATUS(status);
 }
 
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 16d8b6c..9296e86 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -185,459 +185,453 @@
 /* Index           Name                 Parser Args               Interpreter Args                ObjectType                    Class                      Type                  Flags */
 
 /* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER,
-			 AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+		 AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
 /* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER,
-			 AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+		 AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
 /* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP,
-			 ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_SIMPLE,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_SIMPLE,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP,
-			 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, AML_CONSTANT),
+		 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, AML_CONSTANT),
 /* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP,
-			 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, AML_CONSTANT),
+		 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, AML_CONSTANT),
 /* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP,
-			 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, AML_CONSTANT),
+		 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, AML_CONSTANT),
 /* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP,
-			 ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, AML_CONSTANT),
+		 ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, AML_CONSTANT),
 /* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
-			 ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_NO_OBJ,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_NO_OBJ,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP,
-			 ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_OBJECT,
-			 AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+		 ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_OBJECT,
+		 AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
 /* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP,
-			 ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_OBJECT,
-			 AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+		 ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_OBJECT,
+		 AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
 /* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP,
-			 ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_COMPLEX,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED | AML_DEFER),
+		 ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_COMPLEX,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LOCAL_VARIABLE, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LOCAL_VARIABLE, 0),
 /* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_METHOD_ARGUMENT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_METHOD_ARGUMENT, 0),
 /* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R),
 /* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
-			 AML_FLAGS_EXEC_1A_0T_1R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+		 AML_FLAGS_EXEC_1A_0T_1R),
 /* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_1R,
-			 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_1R,
+		 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
 /* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_1R,
-			 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_1R,
+		 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
 /* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_2T_1R,
-			 AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_2T_1R,
+		 AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
 /* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
 /* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP,
-			 ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,
-			 ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
 /* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
 /* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_1R,
-			 AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_1R,
+		 AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
 /* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R),
 /* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
-			 AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
+		 AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
 /* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,
-			 ARGI_CREATE_DWORD_FIELD_OP,
-			 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-			 AML_DEFER | AML_CREATE),
+		 ARGI_CREATE_DWORD_FIELD_OP,
+		 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+		 AML_DEFER | AML_CREATE),
 /* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP,
-			 ARGI_CREATE_WORD_FIELD_OP,
-			 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-			 AML_DEFER | AML_CREATE),
+		 ARGI_CREATE_WORD_FIELD_OP,
+		 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+		 AML_DEFER | AML_CREATE),
 /* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP,
-			 ARGI_CREATE_BYTE_FIELD_OP,
-			 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-			 AML_DEFER | AML_CREATE),
+		 ARGI_CREATE_BYTE_FIELD_OP,
+		 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+		 AML_DEFER | AML_CREATE),
 /* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP,
-			 ARGI_CREATE_BIT_FIELD_OP,
-			 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-			 AML_DEFER | AML_CREATE),
+		 ARGI_CREATE_BIT_FIELD_OP,
+		 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+		 AML_DEFER | AML_CREATE),
 /* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_1R,
-			 AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_1R,
+		 AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
 /* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-			 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
-			 AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
 /* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-			 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
-			 AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
 /* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
-			 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+		 AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
 /* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_0T_1R,
-			 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_0T_1R,
+		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
 /* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_0T_1R,
-			 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_0T_1R,
+		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
 /* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-			 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+		 AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
 /* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+		 AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+		 AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+		 AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+		 AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_CONTROL,
-			 AML_TYPE_CONTROL, AML_HAS_ARGS),
+		 ACPI_TYPE_ANY, AML_CLASS_CONTROL,
+		 AML_TYPE_CONTROL, AML_HAS_ARGS),
 /* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+		 AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+		 ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER,
-			 AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+		 AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
 
 /* Prefixed opcodes (Two-byte opcodes with a prefix op) */
 
 /* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX,
-			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT,
-			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
-			 AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+		 AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
 /* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
 /* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP,
-			 ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
-			 AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-			 AML_DEFER | AML_FIELD | AML_CREATE),
+		 ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
+		 AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+		 AML_DEFER | AML_FIELD | AML_CREATE),
 /* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
-			 AML_FLAGS_EXEC_1A_1T_0R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
+		 AML_FLAGS_EXEC_1A_1T_0R),
 /* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
-			 AML_FLAGS_EXEC_1A_0T_0R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+		 AML_FLAGS_EXEC_1A_0T_0R),
 /* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
-			 AML_FLAGS_EXEC_1A_0T_0R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+		 AML_FLAGS_EXEC_1A_0T_0R),
 /* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
 /* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
 /* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
-			 AML_FLAGS_EXEC_2A_0T_1R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+		 AML_FLAGS_EXEC_2A_0T_1R),
 /* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
-			 AML_FLAGS_EXEC_1A_0T_0R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+		 AML_FLAGS_EXEC_1A_0T_0R),
 /* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
 /* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
 /* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP,
-			 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-			 AML_TYPE_CONSTANT, 0),
+		 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+		 AML_TYPE_CONSTANT, 0),
 /* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_CONSTANT, 0),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_CONSTANT, 0),
 /* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
-			 AML_FLAGS_EXEC_3A_0T_0R),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
+		 AML_FLAGS_EXEC_3A_0T_0R),
 /* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP,
-			 ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_COMPLEX,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED | AML_DEFER),
+		 ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_COMPLEX,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED | AML_DEFER),
 /* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_FIELD),
+		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
 /* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
-			 ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_NO_OBJ,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_NO_OBJ,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP,
-			 ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_SIMPLE,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_SIMPLE,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP,
-			 ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_SIMPLE,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_SIMPLE,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP,
-			 ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
-			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
+		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_FIELD),
+		 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
 /* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_FIELD),
+		 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_FIELD),
 
 /* Internal opcodes that map to invalid AML opcodes */
 
 /* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
-			 AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+		 AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
 /* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
-			 AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+		 AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
 /* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP,
-			 ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
-			 AML_HAS_ARGS | AML_CONSTANT),
+		 ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
+		 AML_HAS_ARGS | AML_CONSTANT),
 /* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP,
-			 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
+		 ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
 /* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP,
-			 ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
-			 AML_TYPE_METHOD_CALL,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
+		 ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
+		 AML_TYPE_METHOD_CALL,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
 /* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, 0),
+		 ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, 0),
 /* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP,
-			 ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+		 ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
 /* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
-			 AML_TYPE_BOGUS,
-			 AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+		 ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+		 AML_TYPE_BOGUS,
+		 AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
 /* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP,
-			 ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+		 ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
 /* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP,
-			 ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+		 ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
 /* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
-			 AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
-			 AML_HAS_ARGS | AML_HAS_RETVAL),
+		 AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
+		 AML_HAS_ARGS | AML_HAS_RETVAL),
 /* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID,
-			 AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
+		 AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
 /* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
-			 AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
+		 AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
 /* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
-			 AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
+		 AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
 
 /* ACPI 2.0 opcodes */
 
 /* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP,
-			 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
-			 AML_TYPE_LITERAL, AML_CONSTANT),
+		 ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+		 AML_TYPE_LITERAL, AML_CONSTANT),
 	/* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP,
 			 ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE,
 			 AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT,
 			 AML_HAS_ARGS | AML_DEFER),
 /* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP,
-			 ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+		 ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,
-			 ARGI_CREATE_QWORD_FIELD_OP,
-			 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
-			 AML_TYPE_CREATE_FIELD,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
-			 AML_DEFER | AML_CREATE),
+		 ARGI_CREATE_QWORD_FIELD_OP,
+		 ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+		 AML_TYPE_CREATE_FIELD,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+		 AML_DEFER | AML_CREATE),
 /* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP,
-			 ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_1T_1R,
-			 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_1T_1R,
+		 AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
 /* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_2A_1T_1R,
-			 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_2A_1T_1R,
+		 AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
 /* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
 /* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
-			 AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
+		 AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
 /* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+		 ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
 /* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
-			 AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
+		 ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+		 AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
 /* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
-			 ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
-			 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE | AML_NAMED),
+		 ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
+		 AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+		 AML_NSNODE | AML_NAMED),
 /* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
-			 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
-			 AML_TYPE_NAMED_NO_OBJ,
-			 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
-			 AML_NSNODE),
+		 ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+		 AML_TYPE_NAMED_NO_OBJ,
+		 AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE),
 
 /* ACPI 3.0 opcodes */
 
 /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
-			 AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
-			 AML_FLAGS_EXEC_0A_0T_1R)
+		 AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+		 AML_FLAGS_EXEC_0A_0T_1R)
 
 /*! [End] no source code translation !*/
 };
diff --git a/drivers/acpi/resources/rscalc.c b/drivers/acpi/resources/rscalc.c
index 8c6d3fd..0dd2ce8 100644
--- a/drivers/acpi/resources/rscalc.c
+++ b/drivers/acpi/resources/rscalc.c
@@ -567,7 +567,8 @@
 						     (*sub_object_list)->string.
 						     length + 1);
 			} else {
-				temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
+				temp_size_needed +=
+				    acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
 			}
 		} else {
 			/*
diff --git a/drivers/acpi/resources/rscreate.c b/drivers/acpi/resources/rscreate.c
index cc48ab0..50da494 100644
--- a/drivers/acpi/resources/rscreate.c
+++ b/drivers/acpi/resources/rscreate.c
@@ -267,16 +267,19 @@
 		 * If BIOS erroneously reversed the _PRT source_name and source_index,
 		 * then reverse them back.
 		 */
-		if (ACPI_GET_OBJECT_TYPE (sub_object_list[3]) != ACPI_TYPE_INTEGER) {
+		if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) !=
+		    ACPI_TYPE_INTEGER) {
 			if (acpi_gbl_enable_interpreter_slack) {
 				source_name_index = 3;
 				source_index_index = 2;
-				printk(KERN_WARNING "ACPI: Handling Garbled _PRT entry\n");
+				printk(KERN_WARNING
+				       "ACPI: Handling Garbled _PRT entry\n");
 			} else {
 				ACPI_ERROR((AE_INFO,
-					"(PRT[%X].source_index) Need Integer, found %s",
-					index,
-					acpi_ut_get_object_type_name(sub_object_list[3])));
+					    "(PRT[%X].source_index) Need Integer, found %s",
+					    index,
+					    acpi_ut_get_object_type_name
+					    (sub_object_list[3])));
 				return_ACPI_STATUS(AE_BAD_DATA);
 			}
 		}
diff --git a/drivers/acpi/resources/rsdump.c b/drivers/acpi/resources/rsdump.c
index de20a5d..46da116 100644
--- a/drivers/acpi/resources/rsdump.c
+++ b/drivers/acpi/resources/rsdump.c
@@ -46,7 +46,6 @@
 
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsdump")
-
 #if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
 /* Local prototypes */
 static void acpi_rs_out_string(char *title, char *value);
@@ -489,10 +488,9 @@
 			/*
 			 * Optional resource_source for Address resources
 			 */
-			acpi_rs_dump_resource_source(ACPI_CAST_PTR
-						     (struct
-						      acpi_resource_source,
-						      target));
+			acpi_rs_dump_resource_source(ACPI_CAST_PTR(struct
+								   acpi_resource_source,
+								   target));
 			break;
 
 		default:
diff --git a/drivers/acpi/resources/rsinfo.c b/drivers/acpi/resources/rsinfo.c
index 7e3c335..2c2adb6 100644
--- a/drivers/acpi/resources/rsinfo.c
+++ b/drivers/acpi/resources/rsinfo.c
@@ -142,7 +142,7 @@
 };
 #endif
 
-#endif	/* ACPI_FUTURE_USAGE */
+#endif				/* ACPI_FUTURE_USAGE */
 /*
  * Base sizes for external AML resource descriptors, indexed by internal type.
  * Includes size of the descriptor header (1 byte for small descriptors,
diff --git a/drivers/acpi/resources/rslist.c b/drivers/acpi/resources/rslist.c
index a92755c..ca21e46 100644
--- a/drivers/acpi/resources/rslist.c
+++ b/drivers/acpi/resources/rslist.c
@@ -153,10 +153,9 @@
 
 		/* Perform the conversion */
 
-		status = acpi_rs_convert_resource_to_aml(resource,
-							 ACPI_CAST_PTR(union
-								       aml_resource,
-								       aml),
+		status = acpi_rs_convert_resource_to_aml(resource, ACPI_CAST_PTR(union
+										 aml_resource,
+										 aml),
 							 acpi_gbl_set_resource_dispatch
 							 [resource->type]);
 		if (ACPI_FAILURE(status)) {
diff --git a/drivers/acpi/resources/rsmisc.c b/drivers/acpi/resources/rsmisc.c
index 3b63b56..c7081af 100644
--- a/drivers/acpi/resources/rsmisc.c
+++ b/drivers/acpi/resources/rsmisc.c
@@ -46,7 +46,6 @@
 
 #define _COMPONENT          ACPI_RESOURCES
 ACPI_MODULE_NAME("rsmisc")
-
 #define INIT_RESOURCE_TYPE(i)       i->resource_offset
 #define INIT_RESOURCE_LENGTH(i)     i->aml_offset
 #define INIT_TABLE_LENGTH(i)        i->value
@@ -429,8 +428,7 @@
 			 * Optional resource_source (Index and String)
 			 */
 			aml_length =
-			    acpi_rs_set_resource_source(aml,
-							(acpi_rs_length)
+			    acpi_rs_set_resource_source(aml, (acpi_rs_length)
 							aml_length, source);
 			acpi_rs_set_resource_length(aml_length, aml);
 			break;
diff --git a/drivers/acpi/resources/rsutils.c b/drivers/acpi/resources/rsutils.c
index 2442a8f..11c0bd7 100644
--- a/drivers/acpi/resources/rsutils.c
+++ b/drivers/acpi/resources/rsutils.c
@@ -353,10 +353,8 @@
 		 *
 		 * Zero the entire area of the buffer.
 		 */
-		total_length =
-		    (u32)
-		    ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) +
-		    1;
+		total_length = (u32)
+		ACPI_STRLEN(ACPI_CAST_PTR(char, &aml_resource_source[1])) + 1;
 		total_length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(total_length);
 
 		ACPI_MEMSET(resource_source->string_ptr, 0, total_length);
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 991f890..f63813a 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -217,7 +217,6 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
-
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -261,7 +260,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
 #endif				/*  ACPI_FUTURE_USAGE  */
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_set_current_resources
@@ -496,7 +494,6 @@
  *              each resource in the list.
  *
  ******************************************************************************/
-
 acpi_status
 acpi_walk_resources(acpi_handle device_handle,
 		    char *name,
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
index 52b2347..bc7e16e 100644
--- a/drivers/acpi/sleep/main.c
+++ b/drivers/acpi/sleep/main.c
@@ -222,7 +222,7 @@
 	.enter = acpi_hibernation_enter,
 	.finish = acpi_hibernation_finish,
 };
-#endif /* CONFIG_SOFTWARE_SUSPEND */
+#endif				/* CONFIG_SOFTWARE_SUSPEND */
 
 /*
  * Toshiba fails to preserve interrupts over S1, reinitialization
@@ -276,4 +276,3 @@
 
 	return 0;
 }
-
diff --git a/drivers/acpi/sleep/proc.c b/drivers/acpi/sleep/proc.c
index 76b45f0..61f1822 100644
--- a/drivers/acpi/sleep/proc.c
+++ b/drivers/acpi/sleep/proc.c
@@ -349,8 +349,7 @@
       end:
 	return_VALUE(result ? result : count);
 }
-#endif	/* HAVE_ACPI_LEGACY_ALARM */
-
+#endif				/* HAVE_ACPI_LEGACY_ALARM */
 
 extern struct list_head acpi_wakeup_device_list;
 extern spinlock_t acpi_device_lock;
@@ -380,8 +379,8 @@
 			   dev->wakeup.state.enabled ? "enabled" : "disabled");
 		if (ldev)
 			seq_printf(seq, "%s:%s",
-				ldev->bus ? ldev->bus->name : "no-bus",
-				ldev->bus_id);
+				   ldev->bus ? ldev->bus->name : "no-bus",
+				   ldev->bus_id);
 		seq_printf(seq, "\n");
 		put_device(ldev);
 
@@ -490,7 +489,7 @@
 
 	return ACPI_INTERRUPT_HANDLED;
 }
-#endif	/* HAVE_ACPI_LEGACY_ALARM */
+#endif				/* HAVE_ACPI_LEGACY_ALARM */
 
 static int __init acpi_sleep_proc_init(void)
 {
@@ -517,7 +516,7 @@
 		entry->proc_fops = &acpi_system_alarm_fops;
 
 	acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
-#endif	/* HAVE_ACPI_LEGACY_ALARM */
+#endif				/* HAVE_ACPI_LEGACY_ALARM */
 
 	/* 'wakeup device' [R/W] */
 	entry =
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c
index 1db833e..1285e91 100644
--- a/drivers/acpi/tables/tbfadt.c
+++ b/drivers/acpi/tables/tbfadt.c
@@ -334,7 +334,8 @@
 				     (acpi_gbl_FADT.xpm1a_event_block.address +
 				      pm1_register_length));
 	/* Don't forget to copy space_id of the GAS */
-	acpi_gbl_xpm1a_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id;
+	acpi_gbl_xpm1a_enable.space_id =
+	    acpi_gbl_FADT.xpm1a_event_block.space_id;
 
 	/* The PM1B register block is optional, ignore if not present */
 
@@ -344,7 +345,8 @@
 					     (acpi_gbl_FADT.xpm1b_event_block.
 					      address + pm1_register_length));
 		/* Don't forget to copy space_id of the GAS */
-		acpi_gbl_xpm1b_enable.space_id = acpi_gbl_FADT.xpm1a_event_block.space_id;
+		acpi_gbl_xpm1b_enable.space_id =
+		    acpi_gbl_FADT.xpm1a_event_block.space_id;
 
 	}
 
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 417ef5f..5b302c4 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -201,6 +201,7 @@
 
 	return_ACPI_STATUS(AE_OK);
 }
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_load_table
@@ -262,7 +263,7 @@
 acpi_status
 acpi_get_table_header(char *signature,
 		      acpi_native_uint instance,
-		      struct acpi_table_header *out_table_header)
+		      struct acpi_table_header * out_table_header)
 {
 	acpi_native_uint i;
 	acpi_native_uint j;
@@ -321,7 +322,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_get_table_header)
 
-
 /******************************************************************************
  *
  * FUNCTION:    acpi_unload_table_id
@@ -346,11 +346,11 @@
 			continue;
 		}
 		/*
-		* Delete all namespace objects owned by this table. Note that these
-		* objects can appear anywhere in the namespace by virtue of the AML
-		* "Scope" operator. Thus, we need to track ownership by an ID, not
-		* simply a position within the hierarchy
-		*/
+		 * Delete all namespace objects owned by this table. Note that these
+		 * objects can appear anywhere in the namespace by virtue of the AML
+		 * "Scope" operator. Thus, we need to track ownership by an ID, not
+		 * simply a position within the hierarchy
+		 */
 		acpi_tb_delete_namespace_by_owner(i);
 		status = acpi_tb_release_owner_id(i);
 		acpi_tb_set_table_loaded_flag(i, FALSE);
@@ -376,7 +376,7 @@
  *****************************************************************************/
 acpi_status
 acpi_get_table(char *signature,
-	       acpi_native_uint instance, struct acpi_table_header ** out_table)
+	       acpi_native_uint instance, struct acpi_table_header **out_table)
 {
 	acpi_native_uint i;
 	acpi_native_uint j;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 589b98b..1ada017 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -59,8 +59,6 @@
 #define ACPI_THERMAL_NOTIFY_CRITICAL	0xF0
 #define ACPI_THERMAL_NOTIFY_HOT		0xF1
 #define ACPI_THERMAL_MODE_ACTIVE	0x00
-#define ACPI_THERMAL_MODE_PASSIVE	0x01
-#define ACPI_THERMAL_MODE_CRITICAL   	0xff
 #define ACPI_THERMAL_PATH_POWEROFF	"/sbin/poweroff"
 
 #define ACPI_THERMAL_MAX_ACTIVE	10
@@ -86,9 +84,6 @@
 static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
 static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_trip_points(struct file *,
-					      const char __user *, size_t,
-					      loff_t *);
 static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
 static ssize_t acpi_thermal_write_cooling_mode(struct file *,
 					       const char __user *, size_t,
@@ -167,7 +162,6 @@
 	unsigned long temperature;
 	unsigned long last_temperature;
 	unsigned long polling_frequency;
-	u8 cooling_mode;
 	volatile u8 zombie;
 	struct acpi_thermal_flags flags;
 	struct acpi_thermal_state state;
@@ -193,7 +187,6 @@
 static const struct file_operations acpi_thermal_trip_fops = {
 	.open = acpi_thermal_trip_open_fs,
 	.read = seq_read,
-	.write = acpi_thermal_write_trip_points,
 	.llseek = seq_lseek,
 	.release = single_release,
 };
@@ -297,11 +290,6 @@
 	if (ACPI_FAILURE(status))
 		return -ENODEV;
 
-	tz->cooling_mode = mode;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n",
-			  mode ? "passive" : "active"));
-
 	return 0;
 }
 
@@ -889,67 +877,6 @@
 	return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
 }
 
-static ssize_t
-acpi_thermal_write_trip_points(struct file *file,
-			       const char __user * buffer,
-			       size_t count, loff_t * ppos)
-{
-	struct seq_file *m = file->private_data;
-	struct acpi_thermal *tz = m->private;
-
-	char *limit_string;
-	int num, critical, hot, passive;
-	int *active;
-	int i = 0;
-
-
-	limit_string = kzalloc(ACPI_THERMAL_MAX_LIMIT_STR_LEN, GFP_KERNEL);
-	if (!limit_string)
-		return -ENOMEM;
-
-	active = kmalloc(ACPI_THERMAL_MAX_ACTIVE * sizeof(int), GFP_KERNEL);
-	if (!active) {
-		kfree(limit_string);
-		return -ENOMEM;
-	}
-
-	if (!tz || (count > ACPI_THERMAL_MAX_LIMIT_STR_LEN - 1)) {
-		count = -EINVAL;
-		goto end;
-	}
-
-	if (copy_from_user(limit_string, buffer, count)) {
-		count = -EFAULT;
-		goto end;
-	}
-
-	limit_string[count] = '\0';
-
-	num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
-		     &critical, &hot, &passive,
-		     &active[0], &active[1], &active[2], &active[3], &active[4],
-		     &active[5], &active[6], &active[7], &active[8],
-		     &active[9]);
-	if (!(num >= 5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) {
-		count = -EINVAL;
-		goto end;
-	}
-
-	tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical);
-	tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot);
-	tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive);
-	for (i = 0; i < num - 3; i++) {
-		if (!(tz->trips.active[i].flags.valid))
-			break;
-		tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]);
-	}
-
-      end:
-	kfree(active);
-	kfree(limit_string);
-	return count;
-}
-
 static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
 {
 	struct acpi_thermal *tz = seq->private;
@@ -958,15 +885,10 @@
 	if (!tz)
 		goto end;
 
-	if (!tz->flags.cooling_mode) {
+	if (!tz->flags.cooling_mode)
 		seq_puts(seq, "<setting not supported>\n");
-	}
-
-	if (tz->cooling_mode == ACPI_THERMAL_MODE_CRITICAL)
-		seq_printf(seq, "cooling mode:	critical\n");
 	else
-		seq_printf(seq, "cooling mode:	%s\n",
-			   tz->cooling_mode ? "passive" : "active");
+		seq_puts(seq, "0 - Active; 1 - Passive\n");
 
       end:
 	return 0;
@@ -1223,28 +1145,6 @@
 	result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE);
 	if (!result)
 		tz->flags.cooling_mode = 1;
-	else {
-		/* Oh,we have not _SCP method.
-		   Generally show cooling_mode by _ACx, _PSV,spec 12.2 */
-		tz->flags.cooling_mode = 0;
-		if (tz->trips.active[0].flags.valid
-		    && tz->trips.passive.flags.valid) {
-			if (tz->trips.passive.temperature >
-			    tz->trips.active[0].temperature)
-				tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
-			else
-				tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
-		} else if (!tz->trips.active[0].flags.valid
-			   && tz->trips.passive.flags.valid) {
-			tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE;
-		} else if (tz->trips.active[0].flags.valid
-			   && !tz->trips.passive.flags.valid) {
-			tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE;
-		} else {
-			/* _ACx and _PSV are optional, but _CRT is required */
-			tz->cooling_mode = ACPI_THERMAL_MODE_CRITICAL;
-		}
-	}
 
 	/* Get default polling frequency [_TZP] (optional) */
 	if (tzp)
diff --git a/drivers/acpi/utilities/utalloc.c b/drivers/acpi/utilities/utalloc.c
index 55a7648..6e56d5f 100644
--- a/drivers/acpi/utilities/utalloc.c
+++ b/drivers/acpi/utilities/utalloc.c
@@ -107,7 +107,6 @@
 	if (ACPI_FAILURE(status)) {
 		return (status);
 	}
-
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 
 	/* Memory allocation lists */
diff --git a/drivers/acpi/utilities/utcache.c b/drivers/acpi/utilities/utcache.c
index 870f6ed..285a0f5 100644
--- a/drivers/acpi/utilities/utcache.c
+++ b/drivers/acpi/utilities/utcache.c
@@ -45,7 +45,6 @@
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utcache")
-
 #ifdef ACPI_USE_LOCAL_CACHE
 /*******************************************************************************
  *
@@ -64,7 +63,7 @@
 acpi_status
 acpi_os_create_cache(char *cache_name,
 		     u16 object_size,
-		     u16 max_depth, struct acpi_memory_list **return_cache)
+		     u16 max_depth, struct acpi_memory_list ** return_cache)
 {
 	struct acpi_memory_list *cache;
 
diff --git a/drivers/acpi/utilities/utcopy.c b/drivers/acpi/utilities/utcopy.c
index 84d529db..4c1e008 100644
--- a/drivers/acpi/utilities/utcopy.c
+++ b/drivers/acpi/utilities/utcopy.c
@@ -814,7 +814,9 @@
 		/*
 		 * Create the object array
 		 */
-		target_object->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.count + 1) * sizeof(void *));
+		target_object->package.elements =
+		    ACPI_ALLOCATE_ZEROED(((acpi_size) source_object->package.
+					  count + 1) * sizeof(void *));
 		if (!target_object->package.elements) {
 			status = AE_NO_MEMORY;
 			goto error_exit;
diff --git a/drivers/acpi/utilities/utdebug.c b/drivers/acpi/utilities/utdebug.c
index 61ad4f2d..c7e128e 100644
--- a/drivers/acpi/utilities/utdebug.c
+++ b/drivers/acpi/utilities/utdebug.c
@@ -45,7 +45,6 @@
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utdebug")
-
 #ifdef ACPI_DEBUG_OUTPUT
 static acpi_thread_id acpi_gbl_prev_thread_id;
 static char *acpi_gbl_fn_entry_str = "----Entry";
@@ -181,7 +180,8 @@
 		if (ACPI_LV_THREADS & acpi_dbg_level) {
 			acpi_os_printf
 			    ("\n**** Context Switch from TID %lX to TID %lX ****\n\n",
-			     (unsigned long)acpi_gbl_prev_thread_id, (unsigned long)thread_id);
+			     (unsigned long)acpi_gbl_prev_thread_id,
+			     (unsigned long)thread_id);
 		}
 
 		acpi_gbl_prev_thread_id = thread_id;
diff --git a/drivers/acpi/utilities/utdelete.c b/drivers/acpi/utilities/utdelete.c
index 673a0ca..f777ceb 100644
--- a/drivers/acpi/utilities/utdelete.c
+++ b/drivers/acpi/utilities/utdelete.c
@@ -170,6 +170,7 @@
 			acpi_os_delete_mutex(object->mutex.os_mutex);
 			acpi_gbl_global_lock_mutex = NULL;
 		} else {
+			acpi_ex_unlink_mutex(object);
 			acpi_os_delete_mutex(object->mutex.os_mutex);
 		}
 		break;
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c
index af33358..1621655 100644
--- a/drivers/acpi/utilities/utglobal.c
+++ b/drivers/acpi/utilities/utglobal.c
@@ -55,12 +55,10 @@
  * Static global variable initialization.
  *
  ******************************************************************************/
-
 /*
  * We want the debug switches statically initialized so they
  * are already set when the debugger is entered.
  */
-
 /* Debug switch - level and trace mask */
 u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT;
 
@@ -735,5 +733,5 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_dbg_level)
-ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
-ACPI_EXPORT_SYMBOL(acpi_gpe_count)
+    ACPI_EXPORT_SYMBOL(acpi_dbg_layer)
+    ACPI_EXPORT_SYMBOL(acpi_gpe_count)
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 50133ff..2d19f71 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -802,9 +802,8 @@
 
 		valid_digits++;
 
-		if (sign_of0x
-		    && ((valid_digits > 16)
-			|| ((valid_digits > 8) && mode32))) {
+		if (sign_of0x && ((valid_digits > 16)
+				  || ((valid_digits > 8) && mode32))) {
 			/*
 			 * This is to_integer operation case.
 			 * No any restrictions for string-to-integer conversion,
@@ -1049,6 +1048,7 @@
 	acpi_os_vprintf(format, args);
 	acpi_os_printf(" [%X]\n", ACPI_CA_VERSION);
 }
+
 EXPORT_SYMBOL(acpi_ut_exception);
 
 void ACPI_INTERNAL_VAR_XFACE
diff --git a/drivers/acpi/utilities/utmutex.c b/drivers/acpi/utilities/utmutex.c
index cbad2ef..4820bc8 100644
--- a/drivers/acpi/utilities/utmutex.c
+++ b/drivers/acpi/utilities/utmutex.c
@@ -244,7 +244,7 @@
 
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
 			  "Thread %lX attempting to acquire Mutex [%s]\n",
-			  (unsigned long) this_thread_id,
+			  (unsigned long)this_thread_id,
 			  acpi_ut_get_mutex_name(mutex_id)));
 
 	status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
@@ -252,7 +252,7 @@
 	if (ACPI_SUCCESS(status)) {
 		ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
 				  "Thread %lX acquired Mutex [%s]\n",
-				  (unsigned long) this_thread_id,
+				  (unsigned long)this_thread_id,
 				  acpi_ut_get_mutex_name(mutex_id)));
 
 		acpi_gbl_mutex_info[mutex_id].use_count++;
@@ -260,7 +260,7 @@
 	} else {
 		ACPI_EXCEPTION((AE_INFO, status,
 				"Thread %lX could not acquire Mutex [%X]",
-				(unsigned long) this_thread_id, mutex_id));
+				(unsigned long)this_thread_id, mutex_id));
 	}
 
 	return (status);
@@ -287,7 +287,7 @@
 	this_thread_id = acpi_os_get_thread_id();
 	ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
 			  "Thread %lX releasing Mutex [%s]\n",
-			  (unsigned long) this_thread_id,
+			  (unsigned long)this_thread_id,
 			  acpi_ut_get_mutex_name(mutex_id)));
 
 	if (mutex_id > ACPI_MAX_MUTEX) {
diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
index e8fe1ba..cbbd331 100644
--- a/drivers/acpi/utilities/utresrc.c
+++ b/drivers/acpi/utilities/utresrc.c
@@ -46,7 +46,6 @@
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utresrc")
-
 #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
 /*
  * Strings used to decode resource descriptors.
diff --git a/drivers/acpi/utilities/utxface.c b/drivers/acpi/utilities/utxface.c
index de3276f..e9a5780 100644
--- a/drivers/acpi/utilities/utxface.c
+++ b/drivers/acpi/utilities/utxface.c
@@ -337,7 +337,6 @@
 }
 
 ACPI_EXPORT_SYMBOL(acpi_terminate)
-
 #ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
@@ -470,7 +469,6 @@
 
 ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
 #endif				/*  ACPI_FUTURE_USAGE  */
-
 /*****************************************************************************
  *
  * FUNCTION:    acpi_purge_cached_objects
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index c721966..f031b87 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Serial ATA (prod) and Parallel ATA (experimental) drivers"
+	depends on HAS_IOMEM
 
 config ATA
 	tristate "ATA device support"
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 0300e7f5..2e18a63e 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -6,6 +6,7 @@
 #
 
 menu "Auxiliary Display support"
+	depends on PARPORT
 
 config KS0108
 	tristate "KS0108 LCD Controller"
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index 17ee97f..b4c8319 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -444,8 +444,6 @@
 	  this option is dangerous unless the CD-RW media is known good, as we
 	  don't do deferred write error handling yet.
 
-source "drivers/s390/block/Kconfig"
-
 config ATA_OVER_ETH
 	tristate "ATA over Ethernet support"
 	depends on NET
@@ -453,6 +451,8 @@
 	This driver provides Support for ATA over Ethernet block
 	devices like the Coraid EtherDrive (R) Storage Blade.
 
+source "drivers/s390/block/Kconfig"
+
 endmenu
 
 endif
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 0f4203b..6055b9c 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -307,7 +307,9 @@
 
 	if (hu) {
 		struct hci_dev *hdev = hu->hdev;
-		hci_uart_close(hdev);
+
+		if (hdev)
+			hci_uart_close(hdev);
 
 		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
 			hu->proto->close(hu);
@@ -473,12 +475,18 @@
 			tty->low_latency = 1;
 		} else
 			return -EBUSY;
+		break;
 
 	case HCIUARTGETPROTO:
 		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
 			return hu->proto->id;
 		return -EUNATCH;
 
+	case HCIUARTGETDEVICE:
+		if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
+			return hu->hdev->id;
+		return -EUNATCH;
+
 	default:
 		err = n_tty_ioctl(tty, file, cmd, arg);
 		break;
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index b250e67..1097ce7 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -28,8 +28,9 @@
 #endif
 
 /* Ioctls */
-#define HCIUARTSETPROTO	_IOW('U', 200, int)
-#define HCIUARTGETPROTO	_IOR('U', 201, int)
+#define HCIUARTSETPROTO		_IOW('U', 200, int)
+#define HCIUARTGETPROTO		_IOR('U', 201, int)
+#define HCIUARTGETDEVICE	_IOR('U', 202, int)
 
 /* UART protocols */
 #define HCI_UART_MAX_PROTO	4
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 2df42fd..abcafac 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -6,6 +6,7 @@
 
 config VT
 	bool "Virtual terminal" if EMBEDDED
+	depends on !S390
 	select INPUT
 	default y if !VIOCONS
 	---help---
@@ -81,6 +82,7 @@
 
 config SERIAL_NONSTANDARD
 	bool "Non-standard serial port support"
+	depends on HAS_IOMEM
 	---help---
 	  Say Y here if you have any non-standard serial boards -- boards
 	  which aren't supported using the standard "dumb" serial driver.
@@ -765,7 +767,7 @@
 
 config RTC
 	tristate "Enhanced Real Time Clock Support"
-	depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH
+	depends on !PPC && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM && !SUPERH && !S390
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -813,7 +815,7 @@
 
 config GEN_RTC
 	tristate "Generic /dev/rtc emulation"
-	depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV
+	depends on RTC!=y && !IA64 && !ARM && !M32R && !SPARC && !FRV && !S390
 	---help---
 	  If you say Y here and create a character special file /dev/rtc with
 	  major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -858,6 +860,7 @@
 
 config DTLK
 	tristate "Double Talk PC internal speech card support"
+	depends on ISA
 	help
 	  This driver is for the DoubleTalk PC, a speech synthesizer
 	  manufactured by RC Systems (<http://www.rcsys.com/>).  It is also
@@ -1043,7 +1046,7 @@
 
 config HANGCHECK_TIMER
 	tristate "Hangcheck timer"
-	depends on X86 || IA64 || PPC64
+	depends on X86 || IA64 || PPC64 || S390
 	help
 	  The hangcheck-timer module detects when the system has gone
 	  out to lunch past a certain margin.  It can reboot the system
@@ -1078,5 +1081,7 @@
 	depends on ISA || PCI
 	default y
 
+source "drivers/s390/char/Kconfig"
+
 endmenu
 
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index c9f0f25..801abdd 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -268,7 +268,7 @@
 		printk(KERN_ERR PFX "Aperture too small (%d MB)\n", size>>20);
 		return 0;
 	}
-	if (aper + size > 0xffffffff) {
+       if ((u64)aper + size > 0x100000000ULL) {
 		printk(KERN_ERR PFX "Aperture out of bounds\n");
 		return 0;
 	}
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index a6dcb29..b894f67 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -3,6 +3,8 @@
 #
 
 menu "IPMI"
+	depends on HAS_IOMEM
+
 config IPMI_HANDLER
        tristate 'IPMI top-level message handler'
        help
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index 6ac3ca4..b3d4ccc 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -1544,21 +1544,18 @@
 }
 
 struct tty_ldisc tty_ldisc_N_TTY = {
-	TTY_LDISC_MAGIC,	/* magic */
-	"n_tty",		/* name */
-	0,			/* num */
-	0,			/* flags */
-	n_tty_open,		/* open */
-	n_tty_close,		/* close */
-	n_tty_flush_buffer,	/* flush_buffer */
-	n_tty_chars_in_buffer,	/* chars_in_buffer */
-	read_chan,		/* read */
-	write_chan,		/* write */
-	n_tty_ioctl,		/* ioctl */
-	n_tty_set_termios,	/* set_termios */
-	normal_poll,		/* poll */
-	NULL,			/* hangup */
-	n_tty_receive_buf,	/* receive_buf */
-	n_tty_write_wakeup	/* write_wakeup */
+	.magic           = TTY_LDISC_MAGIC,
+	.name            = "n_tty",
+	.open            = n_tty_open,
+	.close           = n_tty_close,
+	.flush_buffer    = n_tty_flush_buffer,
+	.chars_in_buffer = n_tty_chars_in_buffer,
+	.read            = read_chan,
+	.write           = write_chan,
+	.ioctl           = n_tty_ioctl,
+	.set_termios     = n_tty_set_termios,
+	.poll            = normal_poll,
+	.receive_buf     = n_tty_receive_buf,
+	.write_wakeup    = n_tty_write_wakeup
 };
 
diff --git a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c
index 245f031..8cc60b6 100644
--- a/drivers/char/rio/riocmd.c
+++ b/drivers/char/rio/riocmd.c
@@ -402,7 +402,7 @@
 		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
 		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);
 
-		if (Rup >= (unsigned short) MAX_RUP) {
+		if (Rup < (unsigned short) MAX_RUP) {
 			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
 		} else
 			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 61a63da..a3fd7e7 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1014,9 +1014,6 @@
 	/*
 	 * Info->count is now 1; so it's safe to sleep now.
 	 */
-	info->session = process_session(current);
-	info->pgrp = process_group(current);
-
 	if ((info->flags & ROCKET_INITIALIZED) == 0) {
 		cp = &info->channel;
 		sSetRxTrigger(cp, TRIG_1);
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 89b4d7b..b4c53df 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1158,8 +1158,6 @@
 	int xmit_head;
 	int xmit_tail;
 	int xmit_cnt;
-	int session;
-	int pgrp;
 	int cd_status;
 	int ignore_status_mask;
 	int read_status_mask;
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2a7736b..02b49bc 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1171,6 +1171,112 @@
 }
 
 /*
+ * support for 32 bit ioctl calls on 64 bit systems
+ */
+#ifdef CONFIG_COMPAT
+static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params)
+{
+	struct MGSL_PARAMS32 tmp_params;
+
+	DBGINFO(("%s get_params32\n", info->device_name));
+	tmp_params.mode            = (compat_ulong_t)info->params.mode;
+	tmp_params.loopback        = info->params.loopback;
+	tmp_params.flags           = info->params.flags;
+	tmp_params.encoding        = info->params.encoding;
+	tmp_params.clock_speed     = (compat_ulong_t)info->params.clock_speed;
+	tmp_params.addr_filter     = info->params.addr_filter;
+	tmp_params.crc_type        = info->params.crc_type;
+	tmp_params.preamble_length = info->params.preamble_length;
+	tmp_params.preamble        = info->params.preamble;
+	tmp_params.data_rate       = (compat_ulong_t)info->params.data_rate;
+	tmp_params.data_bits       = info->params.data_bits;
+	tmp_params.stop_bits       = info->params.stop_bits;
+	tmp_params.parity          = info->params.parity;
+	if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32)))
+		return -EFAULT;
+	return 0;
+}
+
+static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params)
+{
+	struct MGSL_PARAMS32 tmp_params;
+
+	DBGINFO(("%s set_params32\n", info->device_name));
+	if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32)))
+		return -EFAULT;
+
+	spin_lock(&info->lock);
+	info->params.mode            = tmp_params.mode;
+	info->params.loopback        = tmp_params.loopback;
+	info->params.flags           = tmp_params.flags;
+	info->params.encoding        = tmp_params.encoding;
+	info->params.clock_speed     = tmp_params.clock_speed;
+	info->params.addr_filter     = tmp_params.addr_filter;
+	info->params.crc_type        = tmp_params.crc_type;
+	info->params.preamble_length = tmp_params.preamble_length;
+	info->params.preamble        = tmp_params.preamble;
+	info->params.data_rate       = tmp_params.data_rate;
+	info->params.data_bits       = tmp_params.data_bits;
+	info->params.stop_bits       = tmp_params.stop_bits;
+	info->params.parity          = tmp_params.parity;
+	spin_unlock(&info->lock);
+
+ 	change_params(info);
+
+	return 0;
+}
+
+static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
+			 unsigned int cmd, unsigned long arg)
+{
+	struct slgt_info *info = tty->driver_data;
+	int rc = -ENOIOCTLCMD;
+
+	if (sanity_check(info, tty->name, "compat_ioctl"))
+		return -ENODEV;
+	DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
+
+	switch (cmd) {
+
+	case MGSL_IOCSPARAMS32:
+		rc = set_params32(info, compat_ptr(arg));
+		break;
+
+	case MGSL_IOCGPARAMS32:
+		rc = get_params32(info, compat_ptr(arg));
+		break;
+
+	case MGSL_IOCGPARAMS:
+	case MGSL_IOCSPARAMS:
+	case MGSL_IOCGTXIDLE:
+	case MGSL_IOCGSTATS:
+	case MGSL_IOCWAITEVENT:
+	case MGSL_IOCGIF:
+	case MGSL_IOCSGPIO:
+	case MGSL_IOCGGPIO:
+	case MGSL_IOCWAITGPIO:
+	case TIOCGICOUNT:
+		rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
+		break;
+
+	case MGSL_IOCSTXIDLE:
+	case MGSL_IOCTXENABLE:
+	case MGSL_IOCRXENABLE:
+	case MGSL_IOCTXABORT:
+	case TIOCMIWAIT:
+	case MGSL_IOCSIF:
+		rc = ioctl(tty, file, cmd, arg);
+		break;
+	}
+
+	DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
+	return rc;
+}
+#else
+#define slgt_compat_ioctl NULL
+#endif /* ifdef CONFIG_COMPAT */
+
+/*
  * proc fs support
  */
 static inline int line_info(char *buf, struct slgt_info *info)
@@ -3446,6 +3552,7 @@
 	.chars_in_buffer = chars_in_buffer,
 	.flush_buffer = flush_buffer,
 	.ioctl = ioctl,
+	.compat_ioctl = slgt_compat_ioctl,
 	.throttle = throttle,
 	.unthrottle = unthrottle,
 	.send_xchar = send_xchar,
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 11089be..dc4e1ff 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "TPM devices"
+	depends on HAS_IOMEM
 
 config TCG_TPM
 	tristate "TPM Hardware Support"
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index fc662e4..fe62c21 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -151,6 +151,12 @@
 static int tty_release(struct inode *, struct file *);
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+				unsigned long arg);
+#else
+#define tty_compat_ioctl NULL
+#endif
 static int tty_fasync(int fd, struct file * filp, int on);
 static void release_tty(struct tty_struct *tty, int idx);
 static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
@@ -1143,8 +1149,8 @@
 	return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
 }
 
-static int hung_up_tty_ioctl(struct inode * inode, struct file * file,
-			     unsigned int cmd, unsigned long arg)
+static long hung_up_tty_ioctl(struct file * file,
+			      unsigned int cmd, unsigned long arg)
 {
 	return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
 }
@@ -1155,6 +1161,7 @@
 	.write		= tty_write,
 	.poll		= tty_poll,
 	.ioctl		= tty_ioctl,
+	.compat_ioctl	= tty_compat_ioctl,
 	.open		= tty_open,
 	.release	= tty_release,
 	.fasync		= tty_fasync,
@@ -1167,6 +1174,7 @@
 	.write		= tty_write,
 	.poll		= tty_poll,
 	.ioctl		= tty_ioctl,
+	.compat_ioctl	= tty_compat_ioctl,
 	.open		= ptmx_open,
 	.release	= tty_release,
 	.fasync		= tty_fasync,
@@ -1179,6 +1187,7 @@
 	.write		= redirected_tty_write,
 	.poll		= tty_poll,
 	.ioctl		= tty_ioctl,
+	.compat_ioctl	= tty_compat_ioctl,
 	.open		= tty_open,
 	.release	= tty_release,
 	.fasync		= tty_fasync,
@@ -1189,7 +1198,8 @@
 	.read		= hung_up_tty_read,
 	.write		= hung_up_tty_write,
 	.poll		= hung_up_tty_poll,
-	.ioctl		= hung_up_tty_ioctl,
+	.unlocked_ioctl = hung_up_tty_ioctl,
+	.compat_ioctl	= hung_up_tty_ioctl,
 	.release	= tty_release,
 };
 
@@ -3357,6 +3367,32 @@
 	return retval;
 }
 
+#ifdef CONFIG_COMPAT
+static long tty_compat_ioctl(struct file * file, unsigned int cmd,
+				unsigned long arg)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	struct tty_struct *tty = file->private_data;
+	struct tty_ldisc *ld;
+	int retval = -ENOIOCTLCMD;
+
+	if (tty_paranoia_check(tty, inode, "tty_ioctl"))
+		return -EINVAL;
+
+	if (tty->driver->compat_ioctl) {
+		retval = (tty->driver->compat_ioctl)(tty, file, cmd, arg);
+		if (retval != -ENOIOCTLCMD)
+			return retval;
+	}
+
+	ld = tty_ldisc_ref_wait(tty);
+	if (ld->compat_ioctl)
+		retval = ld->compat_ioctl(tty, file, cmd, arg);
+	tty_ldisc_deref(ld);
+
+	return retval;
+}
+#endif
 
 /*
  * This implements the "Secure Attention Key" ---  the idea is to
@@ -3689,6 +3725,7 @@
 	driver->write_room = op->write_room;
 	driver->chars_in_buffer = op->chars_in_buffer;
 	driver->ioctl = op->ioctl;
+	driver->compat_ioctl = op->compat_ioctl;
 	driver->set_termios = op->set_termios;
 	driver->throttle = op->throttle;
 	driver->unthrottle = op->unthrottle;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 60198a7..1cad32c 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -2,9 +2,7 @@
 # Watchdog device configuration
 #
 
-menu "Watchdog Cards"
-
-config WATCHDOG
+menuconfig WATCHDOG
 	bool "Watchdog Timer Support"
 	---help---
 	  If you say Y here (and to one of the following options) and create a
@@ -28,9 +26,10 @@
 
 	  If unsure, say N.
 
+if WATCHDOG
+
 config WATCHDOG_NOWAYOUT
 	bool "Disable watchdog shutdown on close"
-	depends on WATCHDOG
 	help
 	  The default watchdog behaviour (which you get if you say N here) is
 	  to stop the timer if the process managing it closes the file
@@ -43,13 +42,11 @@
 #
 
 comment "Watchdog Device Drivers"
-	depends on WATCHDOG
 
 # Architecture Independent
 
 config SOFT_WATCHDOG
 	tristate "Software watchdog"
-	depends on WATCHDOG
 	help
 	  A software monitoring watchdog. This will fail to reboot your system
 	  from some situations that the hardware watchdog will recover
@@ -62,14 +59,14 @@
 
 config AT91RM9200_WATCHDOG
 	tristate "AT91RM9200 watchdog"
-	depends on WATCHDOG && ARCH_AT91RM9200
+	depends on ARCH_AT91RM9200
 	help
 	  Watchdog timer embedded into AT91RM9200 chips. This will reboot your
 	  system when the timeout is reached.
 
 config 21285_WATCHDOG
 	tristate "DC21285 watchdog"
-	depends on WATCHDOG && FOOTBRIDGE
+	depends on FOOTBRIDGE
 	help
 	  The Intel Footbridge chip contains a built-in watchdog circuit. Say Y
 	  here if you wish to use this. Alternatively say M to compile the
@@ -83,7 +80,7 @@
 
 config 977_WATCHDOG
 	tristate "NetWinder WB83C977 watchdog"
-	depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER
+	depends on FOOTBRIDGE && ARCH_NETWINDER
 	help
 	  Say Y here to include support for the WB977 watchdog included in
 	  NetWinder machines. Alternatively say M to compile the driver as
@@ -93,7 +90,7 @@
 
 config IXP2000_WATCHDOG
 	tristate "IXP2000 Watchdog"
-	depends on WATCHDOG && ARCH_IXP2000
+	depends on ARCH_IXP2000
 	help
 	  Say Y here if to include support for the watchdog timer
 	  in the Intel IXP2000(2400, 2800, 2850) network processors.
@@ -104,7 +101,7 @@
 
 config IXP4XX_WATCHDOG
 	tristate "IXP4xx Watchdog"
-	depends on WATCHDOG && ARCH_IXP4XX
+	depends on ARCH_IXP4XX
 	help
 	  Say Y here if to include support for the watchdog timer
 	  in the Intel IXP4xx network processors. This driver can
@@ -120,7 +117,7 @@
 
 config S3C2410_WATCHDOG
 	tristate "S3C2410 Watchdog"
-	depends on WATCHDOG && ARCH_S3C2410
+	depends on ARCH_S3C2410
 	help
 	  Watchdog timer block in the Samsung S3C2410 chips. This will
 	  reboot the system when the timer expires with the watchdog
@@ -136,7 +133,7 @@
 
 config SA1100_WATCHDOG
 	tristate "SA1100/PXA2xx watchdog"
-	depends on WATCHDOG && ( ARCH_SA1100 || ARCH_PXA )
+	depends on ARCH_SA1100 || ARCH_PXA
 	help
 	  Watchdog timer embedded into SA11x0 and PXA2xx chips. This will
 	  reboot your system when timeout is reached.
@@ -148,7 +145,7 @@
 
 config MPCORE_WATCHDOG
 	tristate "MPcore watchdog"
-	depends on WATCHDOG && ARM_MPCORE_PLATFORM && LOCAL_TIMERS
+	depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS
 	help
 	  Watchdog timer embedded into the MPcore system.
 
@@ -157,7 +154,7 @@
 
 config EP93XX_WATCHDOG
 	tristate "EP93xx Watchdog"
-	depends on WATCHDOG && ARCH_EP93XX
+	depends on ARCH_EP93XX
 	help
 	  Say Y here if to include support for the watchdog timer
 	  embedded in the Cirrus Logic EP93xx family of devices.
@@ -167,14 +164,14 @@
 
 config OMAP_WATCHDOG
 	tristate "OMAP Watchdog"
-	depends on WATCHDOG && (ARCH_OMAP16XX || ARCH_OMAP24XX)
+	depends on ARCH_OMAP16XX || ARCH_OMAP24XX
 	help
 	  Support for TI OMAP1610/OMAP1710/OMAP2420 watchdog.  Say 'Y' here to
 	  enable the OMAP1610/OMAP1710 watchdog timer.
 
 config PNX4008_WATCHDOG
 	tristate "PNX4008 Watchdog"
-	depends on WATCHDOG && ARCH_PNX4008
+	depends on ARCH_PNX4008
 	help
 	  Say Y here if to include support for the watchdog timer
 	  in the PNX4008 processor.
@@ -187,7 +184,7 @@
 
 config ACQUIRE_WDT
 	tristate "Acquire SBC Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on Single Board
 	  Computers produced by Acquire Inc (and others). This watchdog
@@ -201,7 +198,7 @@
 
 config ADVANTECH_WDT
 	tristate "Advantech SBC Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  If you are configuring a Linux kernel for the Advantech single-board
 	  computer, say `Y' here to support its built-in watchdog timer
@@ -210,7 +207,7 @@
 
 config ALIM1535_WDT
 	tristate "ALi M1535 PMU Watchdog Timer"
-	depends on WATCHDOG && X86 && PCI
+	depends on X86 && PCI
 	---help---
 	  This is the driver for the hardware watchdog on the ALi M1535 PMU.
 
@@ -221,7 +218,7 @@
 
 config ALIM7101_WDT
 	tristate "ALi M7101 PMU Computer Watchdog"
-	depends on WATCHDOG && X86 && PCI
+	depends on X86 && PCI
 	help
 	  This is the driver for the hardware watchdog on the ALi M7101 PMU
 	  as used in the x86 Cobalt servers.
@@ -233,7 +230,7 @@
 
 config SC520_WDT
 	tristate "AMD Elan SC520 processor Watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  This is the driver for the hardware watchdog built in to the
 	  AMD "Elan" SC520 microcomputer commonly used in embedded systems.
@@ -246,7 +243,7 @@
 
 config EUROTECH_WDT
 	tristate "Eurotech CPU-1220/1410 Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  Enable support for the watchdog timer on the Eurotech CPU-1220 and
 	  CPU-1410 cards.  These are PC/104 SBCs. Spec sheets and product
@@ -254,7 +251,7 @@
 
 config IB700_WDT
 	tristate "IB700 SBC Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on the IB700 Single
 	  Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog
@@ -270,7 +267,7 @@
 
 config IBMASR
 	tristate "IBM Automatic Server Restart"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  This is the driver for the IBM Automatic Server Restart watchdog
 	  timer built-in into some eServer xSeries machines.
@@ -280,7 +277,7 @@
 
 config WAFER_WDT
 	tristate "ICP Wafer 5823 Single Board Computer Watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  This is a driver for the hardware watchdog on the ICP Wafer 5823
 	  Single Board Computer (and probably other similar models).
@@ -290,7 +287,7 @@
 
 config I6300ESB_WDT
 	tristate "Intel 6300ESB Timer/Watchdog"
-	depends on WATCHDOG && X86 && PCI
+	depends on X86 && PCI
 	---help---
 	  Hardware driver for the watchdog timer built into the Intel
 	  6300ESB controller hub.
@@ -298,31 +295,9 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called i6300esb.
 
-config I8XX_TCO
-	tristate "Intel i8xx TCO Timer/Watchdog"
-	depends on WATCHDOG && (X86 || IA64) && PCI
-	default n
-	---help---
-	  Hardware driver for the TCO timer built into the Intel 82801
-	  I/O Controller Hub family.  The TCO (Total Cost of Ownership)
-	  timer is a watchdog timer that will reboot the machine after
-	  its second expiration. The expiration time can be configured
-	  with the "heartbeat" parameter.
-
-	  On some motherboards the driver may fail to reset the chipset's
-	  NO_REBOOT flag which prevents the watchdog from rebooting the
-	  machine. If this is the case you will get a kernel message like
-	  "failed to reset NO_REBOOT flag, reboot disabled by hardware".
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called i8xx_tco.
-
-	  Note: This driver will be removed in the near future. Please
-	  use the Intel TCO Timer/Watchdog driver.
-
 config ITCO_WDT
 	tristate "Intel TCO Timer/Watchdog"
-	depends on WATCHDOG && (X86 || IA64) && PCI
+	depends on (X86 || IA64) && PCI
 	---help---
 	  Hardware driver for the intel TCO timer based watchdog devices.
 	  These drivers are included in the Intel 82801 I/O Controller
@@ -351,7 +326,7 @@
 
 config SC1200_WDT
 	tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  This is a driver for National Semiconductor PC87307/PC97307 hardware
 	  watchdog cards as found on the SC1200. This watchdog is mainly used
@@ -365,7 +340,7 @@
 
 config SCx200_WDT
 	tristate "National Semiconductor SCx200 Watchdog"
-	depends on WATCHDOG && SCx200 && PCI
+	depends on SCx200 && PCI
 	help
 	  Enable the built-in watchdog timer support on the National
 	  Semiconductor SCx200 processors.
@@ -374,7 +349,7 @@
 
 config PC87413_WDT
 	tristate "NS PC87413 watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on the PC87413 chipset
 	  This watchdog simply watches your kernel to make sure it doesn't
@@ -388,7 +363,7 @@
  
 config 60XX_WDT
 	tristate "SBC-60XX Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	help
 	  This driver can be used with the watchdog timer found on some
 	  single board computers, namely the 6010 PII based computer.
@@ -402,7 +377,7 @@
 
 config SBC8360_WDT
 	tristate "SBC8360 Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 
 	  This is the driver for the hardware watchdog on the SBC8360 Single
@@ -415,7 +390,7 @@
 
 config CPU5_WDT
 	tristate "SMA CPU5 Watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  TBD.
 	  To compile this driver as a module, choose M here: the
@@ -423,7 +398,7 @@
 
 config SMSC37B787_WDT
 	tristate "Winbond SMsC37B787 Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog component on the
 	  Winbond SMsC37B787 chipset as used on the NetRunner Mainboard
@@ -443,7 +418,7 @@
 
 config W83627HF_WDT
 	tristate "W83627HF Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on the W83627HF chipset
 	  as used in Advantech PC-9578 and Tyan S2721-533 motherboards
@@ -458,7 +433,7 @@
 
 config W83697HF_WDT
 	tristate "W83697HF/W83697HG Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on the W83697HF/HG
 	  chipset as used in Dedibox/VIA motherboards (and likely others).
@@ -473,7 +448,7 @@
 
 config W83877F_WDT
 	tristate "W83877F (EMACS) Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on the W83877F chipset
 	  as used in EMACS PC-104 motherboards (and likely others).  This
@@ -488,7 +463,7 @@
 
 config W83977F_WDT
 	tristate "W83977F (PCM-5335) Watchdog Timer"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the hardware watchdog on the W83977F I/O chip
 	  as used in AAEON's PCM-5335 SBC (and likely others).  This
@@ -501,7 +476,7 @@
 
 config MACHZ_WDT
 	tristate "ZF MachZ Watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  If you are using a ZF Micro MachZ processor, say Y here, otherwise
 	  N.  This is the driver for the watchdog timer built-in on that
@@ -514,7 +489,7 @@
 
 config SBC_EPX_C3_WATCHDOG
 	tristate "Winsystems SBC EPX-C3 watchdog"
-	depends on WATCHDOG && X86
+	depends on X86
 	---help---
 	  This is the driver for the built-in watchdog timer on the EPX-C3
 	  Single-board computer made by Winsystems, Inc.
@@ -537,19 +512,19 @@
 
 config 8xx_WDT
 	tristate "MPC8xx Watchdog Timer"
-	depends on WATCHDOG && 8xx
+	depends on 8xx
 
 config 83xx_WDT
 	tristate "MPC83xx Watchdog Timer"
-	depends on WATCHDOG && PPC_83xx
+	depends on PPC_83xx
 
 config MV64X60_WDT
 	tristate "MV64X60 (Marvell Discovery) Watchdog Timer"
-	depends on WATCHDOG && MV64X60
+	depends on MV64X60
 
 config BOOKE_WDT
 	bool "PowerPC Book-E Watchdog Timer"
-	depends on WATCHDOG && (BOOKE || 4xx)
+	depends on BOOKE || 4xx
 	---help---
 	  Please see Documentation/watchdog/watchdog-api.txt for
 	  more information.
@@ -558,7 +533,7 @@
 
 config WATCHDOG_RTAS
 	tristate "RTAS watchdog"
-	depends on WATCHDOG && PPC_RTAS
+	depends on PPC_RTAS
 	help
 	  This driver adds watchdog support for the RTAS watchdog.
 
@@ -569,16 +544,23 @@
 
 config INDYDOG
 	tristate "Indy/I2 Hardware Watchdog"
-	depends on WATCHDOG && SGI_IP22
+	depends on SGI_IP22
 	help
 	  Hardware driver for the Indy's/I2's watchdog. This is a
 	  watchdog timer that will reboot the machine after a 60 second
 	  timer expired and no process has written to /dev/watchdog during
 	  that time.
 
+config WDT_MTX1
+	tristate "MTX-1 Hardware Watchdog"
+	depends on MIPS_MTX1
+	help
+	  Hardware driver for the MTX-1 boards. This is a watchdog timer that
+	  will reboot the machine after a 100 seconds timer expired.
+
 config WDT_RM9K_GPI
 	tristate "RM9000/GPI hardware watchdog"
-	depends on WATCHDOG && CPU_RM9000
+	depends on CPU_RM9000
 	help
 	  Watchdog implementation using the GPI hardware found on
 	  PMC-Sierra RM9xxx CPUs.
@@ -590,7 +572,7 @@
 
 config ZVM_WATCHDOG
 	tristate "z/VM Watchdog Timer"
-	depends on WATCHDOG && S390
+	depends on S390
 	help
 	  IBM s/390 and zSeries machines running under z/VM 5.1 or later
 	  provide a virtual watchdog timer to their guest that cause a
@@ -604,7 +586,7 @@
 
 config SH_WDT
 	tristate "SuperH Watchdog"
-	depends on WATCHDOG && SUPERH
+	depends on SUPERH
 	help
 	  This driver adds watchdog support for the integrated watchdog in the
 	  SuperH processors. If you have one of these processors and wish
@@ -631,7 +613,7 @@
 
 config WATCHDOG_CP1XXX
 	tristate "CP1XXX Hardware Watchdog support"
-	depends on WATCHDOG && SPARC64 && PCI
+	depends on SPARC64 && PCI
 	---help---
 	  This is the driver for the hardware watchdog timers present on
 	  Sun Microsystems CompactPCI models CP1400 and CP1500.
@@ -645,7 +627,7 @@
 
 config WATCHDOG_RIO
 	tristate "RIO Hardware Watchdog support"
-	depends on WATCHDOG && SPARC64 && PCI
+	depends on SPARC64 && PCI
 	help
 	  Say Y here to support the hardware watchdog capability on Sun RIO
 	  machines.  The watchdog timeout period is normally one minute but
@@ -656,11 +638,11 @@
 #
 
 comment "ISA-based Watchdog Cards"
-	depends on WATCHDOG && ISA
+	depends on ISA
 
 config PCWATCHDOG
 	tristate "Berkshire Products ISA-PC Watchdog"
-	depends on WATCHDOG && ISA
+	depends on ISA
 	---help---
 	  This is the driver for the Berkshire Products ISA-PC Watchdog card.
 	  This card simply watches your kernel to make sure it doesn't freeze,
@@ -676,7 +658,7 @@
 
 config MIXCOMWD
 	tristate "Mixcom Watchdog"
-	depends on WATCHDOG && ISA
+	depends on ISA
 	---help---
 	  This is a driver for the Mixcom hardware watchdog cards.  This
 	  watchdog simply watches your kernel to make sure it doesn't freeze,
@@ -690,7 +672,7 @@
 
 config WDT
 	tristate "WDT Watchdog timer"
-	depends on WATCHDOG && ISA
+	depends on ISA
 	---help---
 	  If you have a WDT500P or WDT501P watchdog board, say Y here,
 	  otherwise N. It is not possible to probe for this board, which means
@@ -720,11 +702,11 @@
 #
 
 comment "PCI-based Watchdog Cards"
-	depends on WATCHDOG && PCI
+	depends on PCI
 
 config PCIPCWATCHDOG
 	tristate "Berkshire Products PCI-PC Watchdog"
-	depends on WATCHDOG && PCI
+	depends on PCI
 	---help---
 	  This is the driver for the Berkshire Products PCI-PC Watchdog card.
 	  This card simply watches your kernel to make sure it doesn't freeze,
@@ -739,7 +721,7 @@
 
 config WDTPCI
 	tristate "PCI-WDT500/501 Watchdog timer"
-	depends on WATCHDOG && PCI
+	depends on PCI
 	---help---
 	  If you have a PCI-WDT500/501 watchdog board, say Y here, otherwise N.
 
@@ -766,11 +748,11 @@
 #
 
 comment "USB-based Watchdog Cards"
-	depends on WATCHDOG && USB
+	depends on USB
 
 config USBPCWATCHDOG
 	tristate "Berkshire Products USB-PC Watchdog"
-	depends on WATCHDOG && USB
+	depends on USB
 	---help---
 	  This is the driver for the Berkshire Products USB-PC Watchdog card.
 	  This card simply watches your kernel to make sure it doesn't freeze,
@@ -783,4 +765,4 @@
 
 	  Most people will say N.
 
-endmenu
+endif # WATCHDOG
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 2cd8ff8..8bfc00c 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -46,7 +46,6 @@
 obj-$(CONFIG_IBMASR) += ibmasr.o
 obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o
 obj-$(CONFIG_I6300ESB_WDT) += i6300esb.o
-obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o
 obj-$(CONFIG_ITCO_WDT) += iTCO_wdt.o iTCO_vendor_support.o
 obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o
 obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
@@ -73,6 +72,7 @@
 
 # MIPS Architecture
 obj-$(CONFIG_INDYDOG) += indydog.o
+obj-$(CONFIG_WDT_MTX1)	+= mtx-1_wdt.o
 obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
 
 # S390 Architecture
diff --git a/drivers/char/watchdog/cpu5wdt.c b/drivers/char/watchdog/cpu5wdt.c
index bcd7e36..d0d45a8 100644
--- a/drivers/char/watchdog/cpu5wdt.c
+++ b/drivers/char/watchdog/cpu5wdt.c
@@ -220,17 +220,17 @@
 	if ( verbose )
 		printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose);
 
-	if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
-		printk(KERN_ERR PFX "misc_register failed\n");
-		goto no_misc;
-	}
-
 	if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) {
 		printk(KERN_ERR PFX "request_region failed\n");
 		err = -EBUSY;
 		goto no_port;
 	}
 
+	if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) {
+		printk(KERN_ERR PFX "misc_register failed\n");
+		goto no_misc;
+	}
+
 	/* watchdog reboot? */
 	val = inb(port + CPU5WDT_STATUS_REG);
 	val = (val >> 2) & 1;
@@ -250,9 +250,9 @@
 
 	return 0;
 
-no_port:
-	misc_deregister(&cpu5wdt_misc);
 no_misc:
+	release_region(port, CPU5WDT_EXTENT);
+no_port:
 	return err;
 }
 
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
index f70387f..b070324 100644
--- a/drivers/char/watchdog/eurotechwdt.c
+++ b/drivers/char/watchdog/eurotechwdt.c
@@ -413,17 +413,10 @@
 {
 	int ret;
 
-	ret = misc_register(&eurwdt_miscdev);
-	if (ret) {
-		printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
-		WATCHDOG_MINOR);
-		goto out;
-	}
-
 	ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL);
 	if(ret) {
 		printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
-		goto outmisc;
+		goto out;
 	}
 
 	if (!request_region(io, 2, "eurwdt")) {
@@ -438,6 +431,13 @@
 		goto outreg;
 	}
 
+	ret = misc_register(&eurwdt_miscdev);
+	if (ret) {
+		printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
+		WATCHDOG_MINOR);
+		goto outreboot;
+	}
+
 	eurwdt_unlock_chip();
 
 	ret = 0;
@@ -448,14 +448,14 @@
 out:
 	return ret;
 
+outreboot:
+	unregister_reboot_notifier(&eurwdt_notifier);
+
 outreg:
 	release_region(io, 2);
 
 outirq:
 	free_irq(irq, NULL);
-
-outmisc:
-	misc_deregister(&eurwdt_miscdev);
 	goto out;
 }
 
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
deleted file mode 100644
index a62ef48..0000000
--- a/drivers/char/watchdog/i8xx_tco.c
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- *	i8xx_tco:	TCO timer driver for i8xx chipsets
- *
- *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
- *				http://www.kernelconcepts.de
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- *	Neither kernel concepts nor Nils Faerber admit liability nor provide
- *	warranty for any of this software. This material is provided
- *	"AS-IS" and at no charge.
- *
- *	(c) Copyright 2000	kernel concepts <nils@kernelconcepts.de>
- *				developed for
- *                              Jentro AG, Haar/Munich (Germany)
- *
- *	TCO timer driver for i8xx chipsets
- *	based on softdog.c by Alan Cox <alan@redhat.com>
- *
- *	The TCO timer is implemented in the following I/O controller hubs:
- *	(See the intel documentation on http://developer.intel.com.)
- *	82801AA  (ICH)    : document number 290655-003, 290677-014,
- *	82801AB  (ICHO)   : document number 290655-003, 290677-014,
- *	82801BA  (ICH2)   : document number 290687-002, 298242-027,
- *	82801BAM (ICH2-M) : document number 290687-002, 298242-027,
- *	82801CA  (ICH3-S) : document number 290733-003, 290739-013,
- *	82801CAM (ICH3-M) : document number 290716-001, 290718-007,
- *	82801DB  (ICH4)   : document number 290744-001, 290745-020,
- *	82801DBM (ICH4-M) : document number 252337-001, 252663-005,
- *	82801E   (C-ICH)  : document number 273599-001, 273645-002,
- *	82801EB  (ICH5)   : document number 252516-001, 252517-003,
- *	82801ER  (ICH5R)  : document number 252516-001, 252517-003,
- *
- *  20000710 Nils Faerber
- *	Initial Version 0.01
- *  20000728 Nils Faerber
- *	0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
- *  20011214 Matt Domsch <Matt_Domsch@dell.com>
- *	0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
- *	     Didn't add timeout option as i810_margin already exists.
- *  20020224 Joel Becker, Wim Van Sebroeck
- *	0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3,
- *	     add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT.
- *  20020412 Rob Radez <rob@osinvestor.com>, Wim Van Sebroeck
- *	0.05 Fix possible timer_alive race, add expect close support,
- *	     clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and
- *	     WDIOC_SETOPTIONS), made i810tco_getdevice __init,
- *	     removed boot_status, removed tco_timer_read,
- *	     added support for 82801DB and 82801E chipset,
- *	     added support for 82801EB and 8280ER chipset,
- *	     general cleanup.
- *  20030921 Wim Van Sebroeck <wim@iguana.be>
- *	0.06 change i810_margin to heartbeat, use module_param,
- *	     added notify system support, renamed module to i8xx_tco.
- *  20050128 Wim Van Sebroeck <wim@iguana.be>
- *	0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
- *	     chipsets. Also added support for the "undocumented" ICH7 chipset.
- *  20050807 Wim Van Sebroeck <wim@iguana.be>
- *	0.08 Make sure that the watchdog is only "armed" when started.
- *	     (Kernel Bug 4251)
- *  20060416 Wim Van Sebroeck <wim@iguana.be>
- *	0.09 Remove support for the ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW and
- *	     ICH7 chipsets. (See Kernel Bug 6031 - other code will support these
- *	     chipsets)
- */
-
-/*
- *	Includes, defines, variables, module parameters, ...
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include "i8xx_tco.h"
-
-/* Module and version information */
-#define TCO_VERSION "0.09"
-#define TCO_MODULE_NAME "i8xx TCO timer"
-#define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
-#define PFX TCO_MODULE_NAME ": "
-
-/* internal variables */
-static unsigned int ACPIBASE;
-static spinlock_t tco_lock;	/* Guards the hardware */
-static unsigned long timer_alive;
-static char tco_expect_close;
-static struct pci_dev *i8xx_tco_pci;
-
-/* module parameters */
-#define WATCHDOG_HEARTBEAT 30	/* 30 sec default heartbeat (2<heartbeat<39) */
-static int heartbeat = WATCHDOG_HEARTBEAT;  /* in seconds */
-module_param(heartbeat, int, 0);
-MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
-
-static int nowayout = WATCHDOG_NOWAYOUT;
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
-
-/*
- * Some TCO specific functions
- */
-
-static inline unsigned char seconds_to_ticks(int seconds)
-{
-	/* the internal timer is stored as ticks which decrement
-	 * every 0.6 seconds */
-	return (seconds * 10) / 6;
-}
-
-static int tco_timer_start (void)
-{
-	unsigned char val;
-
-	spin_lock(&tco_lock);
-
-	/* disable chipset's NO_REBOOT bit */
-	pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
-	val &= 0xfd;
-	pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
-
-	/* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
-	val = inb (TCO1_CNT + 1);
-	val &= 0xf7;
-	outb (val, TCO1_CNT + 1);
-	val = inb (TCO1_CNT + 1);
-
-	spin_unlock(&tco_lock);
-
-	if (val & 0x08)
-		return -1;
-	return 0;
-}
-
-static int tco_timer_stop (void)
-{
-	unsigned char val, val1;
-
-	spin_lock(&tco_lock);
-	/* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
-	val = inb (TCO1_CNT + 1);
-	val |= 0x08;
-	outb (val, TCO1_CNT + 1);
-	val = inb (TCO1_CNT + 1);
-
-	/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
-	pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
-	val1 |= 0x02;
-	pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
-
-	spin_unlock(&tco_lock);
-
-	if ((val & 0x08) == 0)
-		return -1;
-	return 0;
-}
-
-static int tco_timer_keepalive (void)
-{
-	spin_lock(&tco_lock);
-	/* Reload the timer by writing to the TCO Timer Reload register */
-	outb (0x01, TCO1_RLD);
-	spin_unlock(&tco_lock);
-	return 0;
-}
-
-static int tco_timer_set_heartbeat (int t)
-{
-	unsigned char val;
-	unsigned char tmrval;
-
-	tmrval = seconds_to_ticks(t);
-	/* from the specs: */
-	/* "Values of 0h-3h are ignored and should not be attempted" */
-	if (tmrval > 0x3f || tmrval < 0x04)
-		return -EINVAL;
-
-	/* Write new heartbeat to watchdog */
-	spin_lock(&tco_lock);
-	val = inb (TCO1_TMR);
-	val &= 0xc0;
-	val |= tmrval;
-	outb (val, TCO1_TMR);
-	val = inb (TCO1_TMR);
-	spin_unlock(&tco_lock);
-
-	if ((val & 0x3f) != tmrval)
-		return -EINVAL;
-
-	heartbeat = t;
-	return 0;
-}
-
-static int tco_timer_get_timeleft (int *time_left)
-{
-	unsigned char val;
-
-	spin_lock(&tco_lock);
-
-	/* read the TCO Timer */
-	val = inb (TCO1_RLD);
-	val &= 0x3f;
-
-	spin_unlock(&tco_lock);
-
-	*time_left = (int)((val * 6) / 10);
-
-	return 0;
-}
-
-/*
- *	/dev/watchdog handling
- */
-
-static int i8xx_tco_open (struct inode *inode, struct file *file)
-{
-	/* /dev/watchdog can only be opened once */
-	if (test_and_set_bit(0, &timer_alive))
-		return -EBUSY;
-
-	/*
-	 *      Reload and activate timer
-	 */
-	tco_timer_keepalive ();
-	tco_timer_start ();
-	return nonseekable_open(inode, file);
-}
-
-static int i8xx_tco_release (struct inode *inode, struct file *file)
-{
-	/*
-	 *      Shut off the timer.
-	 */
-	if (tco_expect_close == 42) {
-		tco_timer_stop ();
-	} else {
-		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
-		tco_timer_keepalive ();
-	}
-	clear_bit(0, &timer_alive);
-	tco_expect_close = 0;
-	return 0;
-}
-
-static ssize_t i8xx_tco_write (struct file *file, const char __user *data,
-			      size_t len, loff_t * ppos)
-{
-	/* See if we got the magic character 'V' and reload the timer */
-	if (len) {
-		if (!nowayout) {
-			size_t i;
-
-			/* note: just in case someone wrote the magic character
-			 * five months ago... */
-			tco_expect_close = 0;
-
-			/* scan to see whether or not we got the magic character */
-			for (i = 0; i != len; i++) {
-				char c;
-				if(get_user(c, data+i))
-					return -EFAULT;
-				if (c == 'V')
-					tco_expect_close = 42;
-			}
-		}
-
-		/* someone wrote to us, we should reload the timer */
-		tco_timer_keepalive ();
-	}
-	return len;
-}
-
-static int i8xx_tco_ioctl (struct inode *inode, struct file *file,
-			  unsigned int cmd, unsigned long arg)
-{
-	int new_options, retval = -EINVAL;
-	int new_heartbeat;
-	int time_left;
-	void __user *argp = (void __user *)arg;
-	int __user *p = argp;
-	static struct watchdog_info ident = {
-		.options =		WDIOF_SETTIMEOUT |
-					WDIOF_KEEPALIVEPING |
-					WDIOF_MAGICCLOSE,
-		.firmware_version =	0,
-		.identity =		TCO_MODULE_NAME,
-	};
-
-	switch (cmd) {
-		case WDIOC_GETSUPPORT:
-			return copy_to_user(argp, &ident,
-				sizeof (ident)) ? -EFAULT : 0;
-
-		case WDIOC_GETSTATUS:
-		case WDIOC_GETBOOTSTATUS:
-			return put_user (0, p);
-
-		case WDIOC_KEEPALIVE:
-			tco_timer_keepalive ();
-			return 0;
-
-		case WDIOC_SETOPTIONS:
-		{
-			if (get_user (new_options, p))
-				return -EFAULT;
-
-			if (new_options & WDIOS_DISABLECARD) {
-				tco_timer_stop ();
-				retval = 0;
-			}
-
-			if (new_options & WDIOS_ENABLECARD) {
-				tco_timer_keepalive ();
-				tco_timer_start ();
-				retval = 0;
-			}
-
-			return retval;
-		}
-
-		case WDIOC_SETTIMEOUT:
-		{
-			if (get_user(new_heartbeat, p))
-				return -EFAULT;
-
-			if (tco_timer_set_heartbeat(new_heartbeat))
-				return -EINVAL;
-
-			tco_timer_keepalive ();
-			/* Fall */
-		}
-
-		case WDIOC_GETTIMEOUT:
-			return put_user(heartbeat, p);
-
-		case WDIOC_GETTIMELEFT:
-		{
-			if (tco_timer_get_timeleft(&time_left))
-				return -EINVAL;
-
-			return put_user(time_left, p);
-		}
-
-		default:
-			return -ENOTTY;
-	}
-}
-
-/*
- *	Notify system
- */
-
-static int i8xx_tco_notify_sys (struct notifier_block *this, unsigned long code, void *unused)
-{
-	if (code==SYS_DOWN || code==SYS_HALT) {
-		/* Turn the WDT off */
-		tco_timer_stop ();
-	}
-
-	return NOTIFY_DONE;
-}
-
-/*
- *	Kernel Interfaces
- */
-
-static const struct file_operations i8xx_tco_fops = {
-	.owner =	THIS_MODULE,
-	.llseek =	no_llseek,
-	.write =	i8xx_tco_write,
-	.ioctl =	i8xx_tco_ioctl,
-	.open =		i8xx_tco_open,
-	.release =	i8xx_tco_release,
-};
-
-static struct miscdevice i8xx_tco_miscdev = {
-	.minor =	WATCHDOG_MINOR,
-	.name =		"watchdog",
-	.fops =		&i8xx_tco_fops,
-};
-
-static struct notifier_block i8xx_tco_notifier = {
-	.notifier_call =	i8xx_tco_notify_sys,
-};
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id i8xx_tco_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1) },
-	{ },			/* End of list */
-};
-MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl);
-
-/*
- *	Init & exit routines
- */
-
-static unsigned char __init i8xx_tco_getdevice (void)
-{
-	struct pci_dev *dev = NULL;
-	u8 val1, val2;
-	u16 badr;
-	/*
-	 *      Find the PCI device
-	 */
-
-	for_each_pci_dev(dev)
-		if (pci_match_id(i8xx_tco_pci_tbl, dev)) {
-			i8xx_tco_pci = dev;
-			break;
-		}
-
-	if (i8xx_tco_pci) {
-		/*
-		 *      Find the ACPI base I/O address which is the base
-		 *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
-		 *      ACPIBASE is bits [15:7] from 0x40-0x43
-		 */
-		pci_read_config_byte (i8xx_tco_pci, 0x40, &val1);
-		pci_read_config_byte (i8xx_tco_pci, 0x41, &val2);
-		badr = ((val2 << 1) | (val1 >> 7)) << 7;
-		ACPIBASE = badr;
-		/* Something's wrong here, ACPIBASE has to be set */
-		if (badr == 0x0001 || badr == 0x0000) {
-			printk (KERN_ERR PFX "failed to get TCOBASE address\n");
-			pci_dev_put(i8xx_tco_pci);
-			return 0;
-		}
-
-		/* Check chipset's NO_REBOOT bit */
-		pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
-		if (val1 & 0x02) {
-			val1 &= 0xfd;
-			pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
-			pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
-			if (val1 & 0x02) {
-				printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
-				pci_dev_put(i8xx_tco_pci);
-				return 0;	/* Cannot reset NO_REBOOT bit */
-			}
-		}
-		/* Disable reboots untill the watchdog starts */
-		val1 |= 0x02;
-		pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
-
-		/* Set the TCO_EN bit in SMI_EN register */
-		if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
-			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-				SMI_EN + 1);
-			pci_dev_put(i8xx_tco_pci);
-			return 0;
-		}
-		val1 = inb (SMI_EN + 1);
-		val1 &= 0xdf;
-		outb (val1, SMI_EN + 1);
-		release_region (SMI_EN + 1, 1);
-		return 1;
-	}
-	return 0;
-}
-
-static int __init watchdog_init (void)
-{
-	int ret;
-
-	spin_lock_init(&tco_lock);
-
-	/* Check whether or not the hardware watchdog is there */
-	if (!i8xx_tco_getdevice () || i8xx_tco_pci == NULL)
-		return -ENODEV;
-
-	if (!request_region (TCOBASE, 0x10, "i8xx TCO")) {
-		printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
-			TCOBASE);
-		ret = -EIO;
-		goto out;
-	}
-
-	/* Clear out the (probably old) status */
-	outb (0, TCO1_STS);
-	outb (3, TCO2_STS);
-
-	/* Check that the heartbeat value is within it's range ; if not reset to the default */
-	if (tco_timer_set_heartbeat (heartbeat)) {
-		heartbeat = WATCHDOG_HEARTBEAT;
-		tco_timer_set_heartbeat (heartbeat);
-		printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39, using %d\n",
-			heartbeat);
-	}
-
-	ret = register_reboot_notifier(&i8xx_tco_notifier);
-	if (ret != 0) {
-		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-			ret);
-		goto unreg_region;
-	}
-
-	ret = misc_register(&i8xx_tco_miscdev);
-	if (ret != 0) {
-		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
-			WATCHDOG_MINOR, ret);
-		goto unreg_notifier;
-	}
-
-	tco_timer_stop ();
-
-	printk (KERN_INFO PFX "initialized (0x%04x). heartbeat=%d sec (nowayout=%d)\n",
-		TCOBASE, heartbeat, nowayout);
-
-	return 0;
-
-unreg_notifier:
-	unregister_reboot_notifier(&i8xx_tco_notifier);
-unreg_region:
-	release_region (TCOBASE, 0x10);
-out:
-	pci_dev_put(i8xx_tco_pci);
-	return ret;
-}
-
-static void __exit watchdog_cleanup (void)
-{
-	/* Stop the timer before we leave */
-	if (!nowayout)
-		tco_timer_stop ();
-
-	/* Deregister */
-	misc_deregister (&i8xx_tco_miscdev);
-	unregister_reboot_notifier(&i8xx_tco_notifier);
-	release_region (TCOBASE, 0x10);
-
-	pci_dev_put(i8xx_tco_pci);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_cleanup);
-
-MODULE_AUTHOR("Nils Faerber");
-MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/i8xx_tco.h b/drivers/char/watchdog/i8xx_tco.h
deleted file mode 100644
index cc14eb8..0000000
--- a/drivers/char/watchdog/i8xx_tco.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *	i8xx_tco:	TCO timer driver for i8xx chipsets
- *
- *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
- *				http://www.kernelconcepts.de
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- *	Neither kernel concepts nor Nils Faerber admit liability nor provide
- *	warranty for any of this software. This material is provided
- *	"AS-IS" and at no charge.
- *
- *	(c) Copyright 2000	kernel concepts <nils@kernelconcepts.de>
- *				developed for
- *                              Jentro AG, Haar/Munich (Germany)
- *
- *	TCO timer driver for i8xx chipsets
- *	based on softdog.c by Alan Cox <alan@redhat.com>
- *
- *	For history and the complete list of supported I/O Controller Hub's
- *	see i8xx_tco.c
- */
-
-
-/*
- * Some address definitions for the TCO
- */
-
-#define	TCOBASE		ACPIBASE + 0x60	/* TCO base address		*/
-#define TCO1_RLD	TCOBASE + 0x00	/* TCO Timer Reload and Current Value */
-#define TCO1_TMR	TCOBASE + 0x01	/* TCO Timer Initial Value	*/
-#define	TCO1_DAT_IN	TCOBASE + 0x02	/* TCO Data In Register		*/
-#define	TCO1_DAT_OUT	TCOBASE + 0x03	/* TCO Data Out Register	*/
-#define	TCO1_STS	TCOBASE + 0x04	/* TCO1 Status Register		*/
-#define	TCO2_STS	TCOBASE + 0x06	/* TCO2 Status Register		*/
-#define TCO1_CNT	TCOBASE + 0x08	/* TCO1 Control Register	*/
-#define TCO2_CNT	TCOBASE + 0x0a	/* TCO2 Control Register	*/
-
-#define	SMI_EN		ACPIBASE + 0x30	/* SMI Control and Enable Register */
diff --git a/drivers/char/watchdog/ibmasr.c b/drivers/char/watchdog/ibmasr.c
index 8195f50..94155f6 100644
--- a/drivers/char/watchdog/ibmasr.c
+++ b/drivers/char/watchdog/ibmasr.c
@@ -367,18 +367,17 @@
 	if (!asr_type)
 		return -ENODEV;
 
+	rc = asr_get_base_address();
+	if (rc)
+		return rc;
+
 	rc = misc_register(&asr_miscdev);
 	if (rc < 0) {
+		release_region(asr_base, asr_length);
 		printk(KERN_ERR PFX "failed to register misc device\n");
 		return rc;
 	}
 
-	rc = asr_get_base_address();
-	if (rc) {
-		misc_deregister(&asr_miscdev);
-		return rc;
-	}
-
 	return 0;
 }
 
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 76c7fa3..a0d2716 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -440,13 +440,6 @@
 	spin_lock_init(&zf_lock);
 	spin_lock_init(&zf_port_lock);
 
-	ret = misc_register(&zf_miscdev);
-	if (ret){
-		printk(KERN_ERR "can't misc_register on minor=%d\n",
-							WATCHDOG_MINOR);
-		goto out;
-	}
-
 	if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
 		printk(KERN_ERR "cannot reserve I/O ports at %d\n",
 							ZF_IOBASE);
@@ -461,16 +454,23 @@
 		goto no_reboot;
 	}
 
+	ret = misc_register(&zf_miscdev);
+	if (ret){
+		printk(KERN_ERR "can't misc_register on minor=%d\n",
+							WATCHDOG_MINOR);
+		goto no_misc;
+	}
+
 	zf_set_status(0);
 	zf_set_control(0);
 
 	return 0;
 
+no_misc:
+	unregister_reboot_notifier(&zf_notifier);
 no_reboot:
 	release_region(ZF_IOBASE, 3);
 no_region:
-	misc_deregister(&zf_miscdev);
-out:
 	return ret;
 }
 
diff --git a/drivers/char/watchdog/mtx-1_wdt.c b/drivers/char/watchdog/mtx-1_wdt.c
new file mode 100644
index 0000000..419ab44
--- /dev/null
+++ b/drivers/char/watchdog/mtx-1_wdt.c
@@ -0,0 +1,238 @@
+/*
+ *      Driver for the MTX-1 Watchdog.
+ *
+ *      (C) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
+ *                              http://www.4g-systems.biz
+ *
+ * 	(C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      Neither Michael Stickel nor 4G Systems admit liability nor provide
+ *      warranty for any of this software. This material is provided
+ *      "AS-IS" and at no charge.
+ *
+ *      (c) Copyright 2005    4G Systems <info@4g-systems.biz>
+ *
+ *      Release 0.01.
+ *      Author: Michael Stickel  michael.stickel@4g-systems.biz
+ *
+ *      Release 0.02.
+ *	Author: Florian Fainelli florian@openwrt.org
+ *		use the Linux watchdog/timer APIs
+ *
+ *      The Watchdog is configured to reset the MTX-1
+ *      if it is not triggered for 100 seconds.
+ *      It should not be triggered more often than 1.6 seconds.
+ *
+ *      A timer triggers the watchdog every 5 seconds, until
+ *      it is opened for the first time. After the first open
+ *      it MUST be triggered every 2..95 seconds.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/timer.h>
+#include <linux/completion.h>
+#include <linux/jiffies.h>
+#include <linux/watchdog.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include <asm/mach-au1x00/au1000.h>
+
+#define MTX1_WDT_INTERVAL	(5 * HZ)
+
+static int ticks = 100 * HZ;
+
+static struct {
+	struct completion stop;
+	volatile int running;
+	struct timer_list timer;
+	volatile int queue;
+	int default_ticks;
+	unsigned long inuse;
+} mtx1_wdt_device;
+
+static void mtx1_wdt_trigger(unsigned long unused)
+{
+	u32 tmp;
+
+	if (mtx1_wdt_device.running)
+		ticks--;
+	/*
+	 * toggle GPIO2_15
+	 */
+	tmp = au_readl(GPIO2_DIR);
+	tmp = (tmp & ~(1<<15)) | ((~tmp) & (1<<15));
+	au_writel (tmp, GPIO2_DIR);
+
+	if (mtx1_wdt_device.queue && ticks)
+		mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
+	else {
+		complete(&mtx1_wdt_device.stop);
+	}
+}
+
+static void mtx1_wdt_reset(void)
+{
+	ticks = mtx1_wdt_device.default_ticks;
+}
+
+
+static void mtx1_wdt_start(void)
+{
+	if (!mtx1_wdt_device.queue) {
+		mtx1_wdt_device.queue = 1;
+		au_writel (au_readl(GPIO2_DIR) | (u32)(1<<15), GPIO2_DIR);
+		mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL);
+	}
+	mtx1_wdt_device.running++;
+}
+
+static int mtx1_wdt_stop(void)
+{
+	if (mtx1_wdt_device.queue) {
+		mtx1_wdt_device.queue = 0;
+		au_writel (au_readl(GPIO2_DIR) & ~((u32)(1<<15)), GPIO2_DIR);
+	}
+
+	ticks = mtx1_wdt_device.default_ticks;
+
+	return 0;
+}
+
+/* Filesystem functions */
+
+static int mtx1_wdt_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &mtx1_wdt_device.inuse))
+		return -EBUSY;
+
+	return nonseekable_open(inode, file);
+}
+
+
+static int mtx1_wdt_release(struct inode *inode, struct file *file)
+{
+	clear_bit(0, &mtx1_wdt_device.inuse);
+	return 0;
+}
+
+static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = (void __user *)arg;
+	unsigned int value;
+	static struct watchdog_info ident =
+	{
+		.options = WDIOF_CARDRESET,
+		.identity = "MTX-1 WDT",
+	};
+
+	switch(cmd) {
+		case WDIOC_KEEPALIVE:
+			mtx1_wdt_reset();
+			break;
+		case WDIOC_GETSTATUS:
+			if ( copy_to_user(argp, &value, sizeof(int)) )
+				return -EFAULT;
+			break;
+		case WDIOC_GETSUPPORT:
+			if ( copy_to_user(argp, &ident, sizeof(ident)) )
+				return -EFAULT;
+			break;
+		case WDIOC_SETOPTIONS:
+			if ( copy_from_user(&value, argp, sizeof(int)) )
+				return -EFAULT;
+			switch(value) {
+				case WDIOS_ENABLECARD:
+					mtx1_wdt_start();
+					break;
+				case WDIOS_DISABLECARD:
+					return mtx1_wdt_stop();
+				default:
+					return -EINVAL;
+			}
+			break;
+		default:
+			return -ENOTTY;
+	}
+	return 0;
+}
+
+
+static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
+{
+	if (!count)
+		return -EIO;
+
+	mtx1_wdt_reset();
+	return count;
+}
+
+static struct file_operations mtx1_wdt_fops = {
+	.owner 		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.ioctl		= mtx1_wdt_ioctl,
+	.open 		= mtx1_wdt_open,
+	.write 		= mtx1_wdt_write,
+	.release 	= mtx1_wdt_release
+};
+
+
+static struct miscdevice mtx1_wdt_misc = {
+	.minor 	= WATCHDOG_MINOR,
+	.name 	= "watchdog",
+	.fops 	= &mtx1_wdt_fops
+};
+
+
+static int __init mtx1_wdt_init(void)
+{
+	int ret;
+
+	if ((ret = misc_register(&mtx1_wdt_misc)) < 0) {
+		printk(KERN_ERR " mtx-1_wdt : failed to register\n");
+		return ret;
+	}
+
+	init_completion(&mtx1_wdt_device.stop);
+	mtx1_wdt_device.queue = 0;
+
+	clear_bit(0, &mtx1_wdt_device.inuse);
+
+	setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
+
+	mtx1_wdt_device.default_ticks = ticks;
+
+	mtx1_wdt_start();
+
+	printk(KERN_INFO "MTX-1 Watchdog driver\n");
+
+	return 0;
+}
+
+static void __exit mtx1_wdt_exit(void)
+{
+	if (mtx1_wdt_device.queue) {
+		mtx1_wdt_device.queue = 0;
+		wait_for_completion(&mtx1_wdt_device.stop);
+	}
+	misc_deregister(&mtx1_wdt_misc);
+}
+
+module_init(mtx1_wdt_init);
+module_exit(mtx1_wdt_exit);
+
+MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
+MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 6e8b570..7b41434 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -59,10 +59,10 @@
 #include <linux/jiffies.h>	/* For jiffies stuff */
 #include <linux/miscdevice.h>	/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
 #include <linux/watchdog.h>	/* For the watchdog specific items */
-#include <linux/notifier.h>	/* For notifier support */
-#include <linux/reboot.h>	/* For reboot_notifier stuff */
+#include <linux/reboot.h>	/* For kernel_power_off() */
 #include <linux/init.h>		/* For __init/__exit/... */
 #include <linux/fs.h>		/* For file operations */
+#include <linux/isa.h>		/* For isa devices */
 #include <linux/ioport.h>	/* For io-port access */
 #include <linux/spinlock.h>	/* For spin_lock/spin_unlock/... */
 
@@ -70,8 +70,8 @@
 #include <asm/io.h>		/* For inb/outb/... */
 
 /* Module and version information */
-#define WATCHDOG_VERSION "1.18"
-#define WATCHDOG_DATE "21 Jan 2007"
+#define WATCHDOG_VERSION "1.20"
+#define WATCHDOG_DATE "18 Feb 2007"
 #define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
 #define WATCHDOG_NAME "pcwd"
 #define PFX WATCHDOG_NAME ": "
@@ -89,6 +89,15 @@
 #define	PCWD_REVISION_C		2
 
 /*
+ * These are the auto-probe addresses available.
+ *
+ * Revision A only uses ports 0x270 and 0x370.  Revision C introduced 0x350.
+ * Revision A has an address range of 2 addresses, while Revision C has 4.
+ */
+#define PCWD_ISA_NR_CARDS	3
+static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
+
+/*
  * These are the defines that describe the control status bits for the
  * PCI-PC Watchdog card.
 */
@@ -485,7 +494,7 @@
 		if (control_status & WD_T110) {
 			*status |= WDIOF_OVERHEAT;
 			if (temp_panic) {
-				printk (KERN_INFO PFX "Temperature overheat trip!\n");
+				printk(KERN_INFO PFX "Temperature overheat trip!\n");
 				kernel_power_off();
 				/* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
 			}
@@ -497,7 +506,7 @@
 		if (control_status & WD_REVC_TTRP) {
 			*status |= WDIOF_OVERHEAT;
 			if (temp_panic) {
-				printk (KERN_INFO PFX "Temperature overheat trip!\n");
+				printk(KERN_INFO PFX "Temperature overheat trip!\n");
 				kernel_power_off();
 				/* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */
 			}
@@ -734,20 +743,6 @@
 }
 
 /*
- *	Notify system
- */
-
-static int pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
-{
-	if (code==SYS_DOWN || code==SYS_HALT) {
-		/* Turn the WDT off */
-		pcwd_stop();
-	}
-
-	return NOTIFY_DONE;
-}
-
-/*
  *	Kernel Interfaces
  */
 
@@ -780,10 +775,6 @@
 	.fops =		&pcwd_temp_fops,
 };
 
-static struct notifier_block pcwd_notifier = {
-	.notifier_call =	pcwd_notify_sys,
-};
-
 /*
  *	Init & exit routines
  */
@@ -803,10 +794,67 @@
 	return r;
 }
 
-static int __devinit pcwatchdog_init(int base_addr)
+/*
+ *  The ISA cards have a heartbeat bit in one of the registers, which
+ *  register is card dependent.  The heartbeat bit is monitored, and if
+ *  found, is considered proof that a Berkshire card has been found.
+ *  The initial rate is once per second at board start up, then twice
+ *  per second for normal operation.
+ */
+static int __devinit pcwd_isa_match(struct device *dev, unsigned int id)
+{
+	int base_addr=pcwd_ioports[id];
+	int port0, last_port0;	/* Reg 0, in case it's REV A */
+	int port1, last_port1;	/* Register 1 for REV C cards */
+	int i;
+	int retval;
+
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n",
+			id);
+
+	if (!request_region (base_addr, 4, "PCWD")) {
+		printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
+		return 0;
+	}
+
+	retval = 0;
+
+	port0 = inb_p(base_addr);	/* For REV A boards */
+	port1 = inb_p(base_addr + 1);	/* For REV C boards */
+	if (port0 != 0xff || port1 != 0xff) {
+		/* Not an 'ff' from a floating bus, so must be a card! */
+		for (i = 0; i < 4; ++i) {
+
+			msleep(500);
+
+			last_port0 = port0;
+			last_port1 = port1;
+
+			port0 = inb_p(base_addr);
+			port1 = inb_p(base_addr + 1);
+
+			/* Has either hearbeat bit changed?  */
+			if ((port0 ^ last_port0) & WD_HRTBT ||
+			    (port1 ^ last_port1) & WD_REVC_HRBT) {
+				retval = 1;
+				break;
+			}
+		}
+	}
+	release_region (base_addr, 4);
+
+	return retval;
+}
+
+static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
 {
 	int ret;
 
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n",
+			id);
+
 	cards_found++;
 	if (cards_found == 1)
 		printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
@@ -816,11 +864,13 @@
 		return -ENODEV;
 	}
 
-	if (base_addr == 0x0000) {
+	if (pcwd_ioports[id] == 0x0000) {
 		printk(KERN_ERR PFX "No I/O-Address for card detected\n");
 		return -ENODEV;
 	}
-	pcwd_private.io_addr = base_addr;
+	pcwd_private.io_addr = pcwd_ioports[id];
+
+	spin_lock_init(&pcwd_private.io_lock);
 
 	/* Check card's revision */
 	pcwd_private.revision = get_revision();
@@ -828,8 +878,8 @@
 	if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
 		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
 			pcwd_private.io_addr);
-		pcwd_private.io_addr = 0x0000;
-		return -EIO;
+		ret=-EIO;
+		goto error_request_region;
 	}
 
 	/* Initial variables */
@@ -865,24 +915,12 @@
 			WATCHDOG_HEARTBEAT);
 	}
 
-	ret = register_reboot_notifier(&pcwd_notifier);
-	if (ret) {
-		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
-			ret);
-		release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
-		pcwd_private.io_addr = 0x0000;
-		return ret;
-	}
-
 	if (pcwd_private.supports_temp) {
 		ret = misc_register(&temp_miscdev);
 		if (ret) {
 			printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 				TEMP_MINOR, ret);
-			unregister_reboot_notifier(&pcwd_notifier);
-			release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
-			pcwd_private.io_addr = 0x0000;
-			return ret;
+			goto error_misc_register_temp;
 		}
 	}
 
@@ -890,22 +928,34 @@
 	if (ret) {
 		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
 			WATCHDOG_MINOR, ret);
-		if (pcwd_private.supports_temp)
-			misc_deregister(&temp_miscdev);
-		unregister_reboot_notifier(&pcwd_notifier);
-		release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
-		pcwd_private.io_addr = 0x0000;
-		return ret;
+		goto error_misc_register_watchdog;
 	}
 
 	printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
 		heartbeat, nowayout);
 
 	return 0;
+
+error_misc_register_watchdog:
+	if (pcwd_private.supports_temp)
+		misc_deregister(&temp_miscdev);
+error_misc_register_temp:
+	release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
+error_request_region:
+	pcwd_private.io_addr = 0x0000;
+	cards_found--;
+	return ret;
 }
 
-static void __devexit pcwatchdog_exit(void)
+static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
 {
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n",
+			id);
+
+	if (!pcwd_private.io_addr)
+		return 1;
+
 	/*  Disable the board  */
 	if (!nowayout)
 		pcwd_stop();
@@ -914,102 +964,50 @@
 	misc_deregister(&pcwd_miscdev);
 	if (pcwd_private.supports_temp)
 		misc_deregister(&temp_miscdev);
-	unregister_reboot_notifier(&pcwd_notifier);
 	release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
 	pcwd_private.io_addr = 0x0000;
 	cards_found--;
-}
-
-/*
- *  The ISA cards have a heartbeat bit in one of the registers, which
- *  register is card dependent.  The heartbeat bit is monitored, and if
- *  found, is considered proof that a Berkshire card has been found.
- *  The initial rate is once per second at board start up, then twice
- *  per second for normal operation.
- */
-static int __init pcwd_checkcard(int base_addr)
-{
-	int port0, last_port0;	/* Reg 0, in case it's REV A */
-	int port1, last_port1;	/* Register 1 for REV C cards */
-	int i;
-	int retval;
-
-	if (!request_region (base_addr, 4, "PCWD")) {
-		printk (KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr);
-		return 0;
-	}
-
-	retval = 0;
-
-	port0 = inb_p(base_addr);	/* For REV A boards */
-	port1 = inb_p(base_addr + 1);	/* For REV C boards */
-	if (port0 != 0xff || port1 != 0xff) {
-		/* Not an 'ff' from a floating bus, so must be a card! */
-		for (i = 0; i < 4; ++i) {
-
-			msleep(500);
-
-			last_port0 = port0;
-			last_port1 = port1;
-
-			port0 = inb_p(base_addr);
-			port1 = inb_p(base_addr + 1);
-
-			/* Has either hearbeat bit changed?  */
-			if ((port0 ^ last_port0) & WD_HRTBT ||
-			    (port1 ^ last_port1) & WD_REVC_HRBT) {
-				retval = 1;
-				break;
-			}
-		}
-	}
-	release_region (base_addr, 4);
-
-	return retval;
-}
-
-/*
- * These are the auto-probe addresses available.
- *
- * Revision A only uses ports 0x270 and 0x370.  Revision C introduced 0x350.
- * Revision A has an address range of 2 addresses, while Revision C has 4.
- */
-static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
-
-static int __init pcwd_init_module(void)
-{
-	int i, found = 0;
-
-	spin_lock_init(&pcwd_private.io_lock);
-
-	for (i = 0; pcwd_ioports[i] != 0; i++) {
-		if (pcwd_checkcard(pcwd_ioports[i])) {
-			if (!(pcwatchdog_init(pcwd_ioports[i])))
-				found++;
-		}
-	}
-
-	if (!found) {
-		printk (KERN_INFO PFX "No card detected, or port not available\n");
-		return -ENODEV;
-	}
 
 	return 0;
 }
 
+static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
+{
+	if (debug >= DEBUG)
+		printk(KERN_DEBUG PFX "pcwd_isa_shutdown id=%d\n",
+			id);
+
+	pcwd_stop();
+}
+
+static struct isa_driver pcwd_isa_driver = {
+	.match		= pcwd_isa_match,
+	.probe		= pcwd_isa_probe,
+	.remove		= __devexit_p(pcwd_isa_remove),
+	.shutdown	= pcwd_isa_shutdown,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= WATCHDOG_NAME,
+	},
+};
+
+static int __init pcwd_init_module(void)
+{
+	return isa_register_driver(&pcwd_isa_driver, PCWD_ISA_NR_CARDS);
+}
+
 static void __exit pcwd_cleanup_module(void)
 {
-	if (pcwd_private.io_addr)
-		pcwatchdog_exit();
-
+	isa_unregister_driver(&pcwd_isa_driver);
 	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
 }
 
 module_init(pcwd_init_module);
 module_exit(pcwd_cleanup_module);
 
-MODULE_AUTHOR("Ken Hollis <kenji@bitgate.com>");
+MODULE_AUTHOR("Ken Hollis <kenji@bitgate.com>, Wim Van Sebroeck <wim@iguana.be>");
 MODULE_DESCRIPTION("Berkshire ISA-PC Watchdog driver");
+MODULE_VERSION(WATCHDOG_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 MODULE_ALIAS_MISCDEV(TEMP_MINOR);
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 31037f9..1e7a671 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -146,7 +146,7 @@
 	atomic_t		cmd_received;		/* true if we received a report after a command */
 
 	int			exists;			/* Wether or not the device exists */
-	struct semaphore	sem;			/* locks this structure */
+	struct mutex		mtx;			/* locks this structure */
 };
 static struct usb_pcwd_private *usb_pcwd_device;
 
@@ -635,7 +635,7 @@
 
 	usb_pcwd_device = usb_pcwd;
 
-	init_MUTEX (&usb_pcwd->sem);
+	mutex_init(&usb_pcwd->mtx);
 	usb_pcwd->udev = udev;
 	usb_pcwd->interface = interface;
 	usb_pcwd->interface_number = iface_desc->desc.bInterfaceNumber;
@@ -763,7 +763,7 @@
 	usb_pcwd = usb_get_intfdata (interface);
 	usb_set_intfdata (interface, NULL);
 
-	down (&usb_pcwd->sem);
+	mutex_lock(&usb_pcwd->mtx);
 
 	/* Stop the timer before we leave */
 	if (!nowayout)
@@ -777,7 +777,7 @@
 	misc_deregister(&usb_pcwd_temperature_miscdev);
 	unregister_reboot_notifier(&usb_pcwd_notifier);
 
-	up (&usb_pcwd->sem);
+	mutex_unlock(&usb_pcwd->mtx);
 
 	/* Delete the USB PCWD device */
 	usb_pcwd_delete(usb_pcwd);
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index dff6cb5..20fa29c 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -379,14 +379,14 @@
 
 	DBG("probe: mapped wdt_base=%p\n", wdt_base);
 
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res == NULL) {
+	wdt_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (wdt_irq == NULL) {
 		printk(KERN_INFO PFX "failed to get irq resource\n");
 		ret = -ENOENT;
 		goto err_map;
 	}
 
-	ret = request_irq(res->start, s3c2410wdt_irq, 0, pdev->name, pdev);
+	ret = request_irq(wdt_irq->start, s3c2410wdt_irq, 0, pdev->name, pdev);
 	if (ret != 0) {
 		printk(KERN_INFO PFX "failed to install irq (%d)\n", ret);
 		goto err_map;
diff --git a/drivers/char/watchdog/sbc8360.c b/drivers/char/watchdog/sbc8360.c
index 67ae426..285d852 100644
--- a/drivers/char/watchdog/sbc8360.c
+++ b/drivers/char/watchdog/sbc8360.c
@@ -333,18 +333,17 @@
 	int res;
 	unsigned long int mseconds = 60000;
 
-	spin_lock_init(&sbc8360_lock);
-	res = misc_register(&sbc8360_miscdev);
-	if (res) {
-		printk(KERN_ERR PFX "failed to register misc device\n");
-		goto out_nomisc;
+	if (timeout < 0 || timeout > 63) {
+		printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
+		res = -EINVAL;
+		goto out;
 	}
 
 	if (!request_region(SBC8360_ENABLE, 1, "SBC8360")) {
 		printk(KERN_ERR PFX "ENABLE method I/O %X is not available.\n",
 		       SBC8360_ENABLE);
 		res = -EIO;
-		goto out_noenablereg;
+		goto out;
 	}
 	if (!request_region(SBC8360_BASETIME, 1, "SBC8360")) {
 		printk(KERN_ERR PFX
@@ -360,10 +359,11 @@
 		goto out_noreboot;
 	}
 
-	if (timeout < 0 || timeout > 63) {
-		printk(KERN_ERR PFX "Invalid timeout index (must be 0-63).\n");
-		res = -EINVAL;
-		goto out_noreboot;
+	spin_lock_init(&sbc8360_lock);
+	res = misc_register(&sbc8360_miscdev);
+	if (res) {
+		printk(KERN_ERR PFX "failed to register misc device\n");
+		goto out_nomisc;
 	}
 
 	wd_margin = wd_times[timeout][0];
@@ -383,13 +383,13 @@
 
 	return 0;
 
-      out_noreboot:
-	release_region(SBC8360_ENABLE, 1);
-	release_region(SBC8360_BASETIME, 1);
-      out_noenablereg:
-      out_nobasetimereg:
-	misc_deregister(&sbc8360_miscdev);
       out_nomisc:
+	unregister_reboot_notifier(&sbc8360_notifier);
+      out_noreboot:
+	release_region(SBC8360_BASETIME, 1);
+      out_nobasetimereg:
+	release_region(SBC8360_ENABLE, 1);
+      out:
 	return res;
 }
 
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index 337ee42..b46e7f4 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -1,5 +1,8 @@
 /*
- *	w83627hf WDT driver
+ *	w83627hf/thf WDT driver
+ *
+ *	(c) Copyright 2007 Vlad Drukker <vlad@storewiz.com>
+ *		added support for W83627THF.
  *
  *	(c) Copyright 2003 Pádraig Brady <P@draigBrady.com>
  *
@@ -39,7 +42,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-#define WATCHDOG_NAME "w83627hf WDT"
+#define WATCHDOG_NAME "w83627hf/thf WDT"
 #define PFX WATCHDOG_NAME ": "
 #define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */
 
@@ -50,7 +53,7 @@
 /* You must set this - there is no sane way to probe for this board. */
 static int wdt_io = 0x2E;
 module_param(wdt_io, int, 0);
-MODULE_PARM_DESC(wdt_io, "w83627hf WDT io port (default 0x2E)");
+MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)");
 
 static int timeout = WATCHDOG_TIMEOUT;	/* in seconds */
 module_param(timeout, int, 0);
@@ -71,9 +74,19 @@
 static void
 w83627hf_select_wd_register(void)
 {
+	unsigned char c;
 	outb_p(0x87, WDT_EFER); /* Enter extended function mode */
 	outb_p(0x87, WDT_EFER); /* Again according to manual */
 
+	outb(0x20, WDT_EFER); 	/* check chip version	*/
+	c = inb(WDT_EFDR);
+	if (c == 0x82) {	/* W83627THF 		*/
+		outb_p(0x2b, WDT_EFER); /* select GPIO3 */
+		c = ((inb_p(WDT_EFDR) & 0xf7) | 0x04); /* select WDT0 */
+		outb_p(0x2b, WDT_EFER);
+		outb_p(c, WDT_EFDR);	/* set GPIO3 to WDT0 */
+	}
+
 	outb_p(0x07, WDT_EFER); /* point to logical device number reg */
 	outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */
 	outb_p(0x30, WDT_EFER); /* select CR30 */
@@ -311,7 +324,7 @@
 
 	spin_lock_init(&io_lock);
 
-	printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF Super I/O chip initialising.\n");
+	printk(KERN_INFO "WDT driver for the Winbond(TM) W83627HF/THF Super I/O chip initialising.\n");
 
 	if (wdt_set_heartbeat(timeout)) {
 		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
@@ -367,5 +380,5 @@
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pádraig Brady <P@draigBrady.com>");
-MODULE_DESCRIPTION("w83627hf WDT driver");
+MODULE_DESCRIPTION("w83627hf/thf WDT driver");
 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index f4c6345..e678a33 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -56,4 +56,26 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called geode-aes.
 
+config ZCRYPT
+	tristate "Support for PCI-attached cryptographic adapters"
+	depends on S390
+	select ZCRYPT_MONOLITHIC if ZCRYPT="y"
+	default "m"
+	help
+	  Select this option if you want to use a PCI-attached cryptographic
+	  adapter like:
+	  + PCI Cryptographic Accelerator (PCICA)
+	  + PCI Cryptographic Coprocessor (PCICC)
+	  + PCI-X Cryptographic Coprocessor (PCIXCC)
+	  + Crypto Express2 Coprocessor (CEX2C)
+	  + Crypto Express2 Accelerator (CEX2A)
+
+config ZCRYPT_MONOLITHIC
+	bool "Monolithic zcrypt module"
+	depends on ZCRYPT="m"
+	help
+	  Select this option if you want to have a single module z90crypt.ko
+	  that contains all parts of the crypto device driver (ap bus,
+	  request router and all the card drivers).
+
 endmenu
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 30d021d..72be6c6 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "DMA Engine support"
+	depends on !S390
 
 config DMA_ENGINE
 	bool "Support for DMA engines"
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 4f08984..807c402 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -7,6 +7,7 @@
 #
 
 menu 'EDAC - error detection and reporting (RAS) (EXPERIMENTAL)'
+	depends on HAS_IOMEM
 
 config EDAC
 	tristate "EDAC core system error reporting (EXPERIMENTAL)"
diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig
new file mode 100644
index 0000000..5932c72
--- /dev/null
+++ b/drivers/firewire/Kconfig
@@ -0,0 +1,61 @@
+# -*- shell-script -*-
+
+comment "An alternative FireWire stack is available with EXPERIMENTAL=y"
+	depends on EXPERIMENTAL=n
+
+config FIREWIRE
+	tristate "IEEE 1394 (FireWire) support (JUJU alternative stack, experimental)"
+	depends on EXPERIMENTAL
+	select CRC_ITU_T
+	help
+	  IEEE 1394 describes a high performance serial bus, which is also
+	  known as FireWire(tm) or i.Link(tm) and is used for connecting all
+	  sorts of devices (most notably digital video cameras) to your
+	  computer.
+
+	  If you have FireWire hardware and want to use it, say Y here.  This
+	  is the core support only, you will also need to select a driver for
+	  your IEEE 1394 adapter.
+
+	  To compile this driver as a module, say M here: the module will be
+	  called fw-core.
+
+	  This is the "JUJU" FireWire stack, an alternative implementation
+	  designed for robustness and simplicity.  You can build either this
+	  stack, or the classic stack (the ieee1394 driver, ohci1394 etc.)
+	  or both.
+
+config FIREWIRE_OHCI
+	tristate "Support for OHCI FireWire host controllers"
+	depends on PCI && FIREWIRE
+	help
+	  Enable this driver if you have a FireWire controller based
+	  on the OHCI specification.  For all practical purposes, this
+	  is the only chipset in use, so say Y here.
+
+	  To compile this driver as a module, say M here:  The module will be
+	  called fw-ohci.
+
+	  If you also build ohci1394 of the classic IEEE 1394 driver stack,
+	  blacklist either ohci1394 or fw-ohci to let hotplug load the desired
+	  driver.
+
+config FIREWIRE_SBP2
+	tristate "Support for storage devices (SBP-2 protocol driver)"
+	depends on FIREWIRE && SCSI
+	help
+	  This option enables you to use SBP-2 devices connected to a
+	  FireWire bus.  SBP-2 devices include storage devices like
+	  harddisks and DVD drives, also some other FireWire devices
+	  like scanners.
+
+	  To compile this driver as a module, say M here:  The module will be
+	  called fw-sbp2.
+
+	  You should also enable support for disks, CD-ROMs, etc. in the SCSI
+	  configuration section.
+
+	  If you also build sbp2 of the classic IEEE 1394 driver stack,
+	  blacklist either sbp2 or fw-sbp2 to let hotplug load the desired
+	  driver.
+
diff --git a/drivers/firewire/Makefile b/drivers/firewire/Makefile
new file mode 100644
index 0000000..fc7d59d
--- /dev/null
+++ b/drivers/firewire/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the Linux IEEE 1394 implementation
+#
+
+fw-core-y += fw-card.o fw-topology.o fw-transaction.o fw-iso.o \
+	fw-device.o fw-cdev.o
+
+obj-$(CONFIG_FIREWIRE) += fw-core.o
+obj-$(CONFIG_FIREWIRE_OHCI) += fw-ohci.o
+obj-$(CONFIG_FIREWIRE_SBP2) += fw-sbp2.o
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c
new file mode 100644
index 0000000..636151a
--- /dev/null
+++ b/drivers/firewire/fw-card.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2005-2007  Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/crc-itu-t.h>
+#include "fw-transaction.h"
+#include "fw-topology.h"
+#include "fw-device.h"
+
+int fw_compute_block_crc(u32 *block)
+{
+	__be32 be32_block[256];
+	int i, length;
+
+	length = (*block >> 16) & 0xff;
+	for (i = 0; i < length; i++)
+		be32_block[i] = cpu_to_be32(block[i + 1]);
+	*block |= crc_itu_t(0, (u8 *) be32_block, length * 4);
+
+	return length;
+}
+
+static DEFINE_MUTEX(card_mutex);
+static LIST_HEAD(card_list);
+
+static LIST_HEAD(descriptor_list);
+static int descriptor_count;
+
+#define BIB_CRC(v)		((v) <<  0)
+#define BIB_CRC_LENGTH(v)	((v) << 16)
+#define BIB_INFO_LENGTH(v)	((v) << 24)
+
+#define BIB_LINK_SPEED(v)	((v) <<  0)
+#define BIB_GENERATION(v)	((v) <<  4)
+#define BIB_MAX_ROM(v)		((v) <<  8)
+#define BIB_MAX_RECEIVE(v)	((v) << 12)
+#define BIB_CYC_CLK_ACC(v)	((v) << 16)
+#define BIB_PMC			((1) << 27)
+#define BIB_BMC			((1) << 28)
+#define BIB_ISC			((1) << 29)
+#define BIB_CMC			((1) << 30)
+#define BIB_IMC			((1) << 31)
+
+static u32 *
+generate_config_rom(struct fw_card *card, size_t *config_rom_length)
+{
+	struct fw_descriptor *desc;
+	static u32 config_rom[256];
+	int i, j, length;
+
+	/*
+	 * Initialize contents of config rom buffer.  On the OHCI
+	 * controller, block reads to the config rom accesses the host
+	 * memory, but quadlet read access the hardware bus info block
+	 * registers.  That's just crack, but it means we should make
+	 * sure the contents of bus info block in host memory mathces
+	 * the version stored in the OHCI registers.
+	 */
+
+	memset(config_rom, 0, sizeof(config_rom));
+	config_rom[0] = BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0);
+	config_rom[1] = 0x31333934;
+
+	config_rom[2] =
+		BIB_LINK_SPEED(card->link_speed) |
+		BIB_GENERATION(card->config_rom_generation++ % 14 + 2) |
+		BIB_MAX_ROM(2) |
+		BIB_MAX_RECEIVE(card->max_receive) |
+		BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC;
+	config_rom[3] = card->guid >> 32;
+	config_rom[4] = card->guid;
+
+	/* Generate root directory. */
+	i = 5;
+	config_rom[i++] = 0;
+	config_rom[i++] = 0x0c0083c0; /* node capabilities */
+	j = i + descriptor_count;
+
+	/* Generate root directory entries for descriptors. */
+	list_for_each_entry (desc, &descriptor_list, link) {
+		if (desc->immediate > 0)
+			config_rom[i++] = desc->immediate;
+		config_rom[i] = desc->key | (j - i);
+		i++;
+		j += desc->length;
+	}
+
+	/* Update root directory length. */
+	config_rom[5] = (i - 5 - 1) << 16;
+
+	/* End of root directory, now copy in descriptors. */
+	list_for_each_entry (desc, &descriptor_list, link) {
+		memcpy(&config_rom[i], desc->data, desc->length * 4);
+		i += desc->length;
+	}
+
+	/* Calculate CRCs for all blocks in the config rom.  This
+	 * assumes that CRC length and info length are identical for
+	 * the bus info block, which is always the case for this
+	 * implementation. */
+	for (i = 0; i < j; i += length + 1)
+		length = fw_compute_block_crc(config_rom + i);
+
+	*config_rom_length = j;
+
+	return config_rom;
+}
+
+static void
+update_config_roms(void)
+{
+	struct fw_card *card;
+	u32 *config_rom;
+	size_t length;
+
+	list_for_each_entry (card, &card_list, link) {
+		config_rom = generate_config_rom(card, &length);
+		card->driver->set_config_rom(card, config_rom, length);
+	}
+}
+
+int
+fw_core_add_descriptor(struct fw_descriptor *desc)
+{
+	size_t i;
+
+	/*
+	 * Check descriptor is valid; the length of all blocks in the
+	 * descriptor has to add up to exactly the length of the
+	 * block.
+	 */
+	i = 0;
+	while (i < desc->length)
+		i += (desc->data[i] >> 16) + 1;
+
+	if (i != desc->length)
+		return -EINVAL;
+
+	mutex_lock(&card_mutex);
+
+	list_add_tail(&desc->link, &descriptor_list);
+	descriptor_count++;
+	if (desc->immediate > 0)
+		descriptor_count++;
+	update_config_roms();
+
+	mutex_unlock(&card_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(fw_core_add_descriptor);
+
+void
+fw_core_remove_descriptor(struct fw_descriptor *desc)
+{
+	mutex_lock(&card_mutex);
+
+	list_del(&desc->link);
+	descriptor_count--;
+	if (desc->immediate > 0)
+		descriptor_count--;
+	update_config_roms();
+
+	mutex_unlock(&card_mutex);
+}
+EXPORT_SYMBOL(fw_core_remove_descriptor);
+
+static const char gap_count_table[] = {
+	63, 5, 7, 8, 10, 13, 16, 18, 21, 24, 26, 29, 32, 35, 37, 40
+};
+
+struct bm_data {
+	struct fw_transaction t;
+	struct {
+		__be32 arg;
+		__be32 data;
+	} lock;
+	u32 old;
+	int rcode;
+	struct completion done;
+};
+
+static void
+complete_bm_lock(struct fw_card *card, int rcode,
+		 void *payload, size_t length, void *data)
+{
+	struct bm_data *bmd = data;
+
+	if (rcode == RCODE_COMPLETE)
+		bmd->old = be32_to_cpu(*(__be32 *) payload);
+	bmd->rcode = rcode;
+	complete(&bmd->done);
+}
+
+static void
+fw_card_bm_work(struct work_struct *work)
+{
+	struct fw_card *card = container_of(work, struct fw_card, work.work);
+	struct fw_device *root;
+	struct bm_data bmd;
+	unsigned long flags;
+	int root_id, new_root_id, irm_id, gap_count, generation, grace;
+	int do_reset = 0;
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	generation = card->generation;
+	root = card->root_node->data;
+	root_id = card->root_node->node_id;
+	grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10));
+
+	if (card->bm_generation + 1 == generation ||
+	    (card->bm_generation != generation && grace)) {
+		/*
+		 * This first step is to figure out who is IRM and
+		 * then try to become bus manager.  If the IRM is not
+		 * well defined (e.g. does not have an active link
+		 * layer or does not responds to our lock request, we
+		 * will have to do a little vigilante bus management.
+		 * In that case, we do a goto into the gap count logic
+		 * so that when we do the reset, we still optimize the
+		 * gap count.  That could well save a reset in the
+		 * next generation.
+		 */
+
+		irm_id = card->irm_node->node_id;
+		if (!card->irm_node->link_on) {
+			new_root_id = card->local_node->node_id;
+			fw_notify("IRM has link off, making local node (%02x) root.\n",
+				  new_root_id);
+			goto pick_me;
+		}
+
+		bmd.lock.arg = cpu_to_be32(0x3f);
+		bmd.lock.data = cpu_to_be32(card->local_node->node_id);
+
+		spin_unlock_irqrestore(&card->lock, flags);
+
+		init_completion(&bmd.done);
+		fw_send_request(card, &bmd.t, TCODE_LOCK_COMPARE_SWAP,
+				irm_id, generation,
+				SCODE_100, CSR_REGISTER_BASE + CSR_BUS_MANAGER_ID,
+				&bmd.lock, sizeof(bmd.lock),
+				complete_bm_lock, &bmd);
+		wait_for_completion(&bmd.done);
+
+		if (bmd.rcode == RCODE_GENERATION) {
+			/*
+			 * Another bus reset happened. Just return,
+			 * the BM work has been rescheduled.
+			 */
+			return;
+		}
+
+		if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f)
+			/* Somebody else is BM, let them do the work. */
+			return;
+
+		spin_lock_irqsave(&card->lock, flags);
+		if (bmd.rcode != RCODE_COMPLETE) {
+			/*
+			 * The lock request failed, maybe the IRM
+			 * isn't really IRM capable after all. Let's
+			 * do a bus reset and pick the local node as
+			 * root, and thus, IRM.
+			 */
+			new_root_id = card->local_node->node_id;
+			fw_notify("BM lock failed, making local node (%02x) root.\n",
+				  new_root_id);
+			goto pick_me;
+		}
+	} else if (card->bm_generation != generation) {
+		/*
+		 * OK, we weren't BM in the last generation, and it's
+		 * less than 100ms since last bus reset. Reschedule
+		 * this task 100ms from now.
+		 */
+		spin_unlock_irqrestore(&card->lock, flags);
+		schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10));
+		return;
+	}
+
+	/*
+	 * We're bus manager for this generation, so next step is to
+	 * make sure we have an active cycle master and do gap count
+	 * optimization.
+	 */
+	card->bm_generation = generation;
+
+	if (root == NULL) {
+		/*
+		 * Either link_on is false, or we failed to read the
+		 * config rom.  In either case, pick another root.
+		 */
+		new_root_id = card->local_node->node_id;
+	} else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) {
+		/*
+		 * If we haven't probed this device yet, bail out now
+		 * and let's try again once that's done.
+		 */
+		spin_unlock_irqrestore(&card->lock, flags);
+		return;
+	} else if (root->config_rom[2] & BIB_CMC) {
+		/*
+		 * FIXME: I suppose we should set the cmstr bit in the
+		 * STATE_CLEAR register of this node, as described in
+		 * 1394-1995, 8.4.2.6.  Also, send out a force root
+		 * packet for this node.
+		 */
+		new_root_id = root_id;
+	} else {
+		/*
+		 * Current root has an active link layer and we
+		 * successfully read the config rom, but it's not
+		 * cycle master capable.
+		 */
+		new_root_id = card->local_node->node_id;
+	}
+
+ pick_me:
+	/* Now figure out what gap count to set. */
+	if (card->topology_type == FW_TOPOLOGY_A &&
+	    card->root_node->max_hops < ARRAY_SIZE(gap_count_table))
+		gap_count = gap_count_table[card->root_node->max_hops];
+	else
+		gap_count = 63;
+
+	/*
+	 * Finally, figure out if we should do a reset or not.  If we've
+	 * done less that 5 resets with the same physical topology and we
+	 * have either a new root or a new gap count setting, let's do it.
+	 */
+
+	if (card->bm_retries++ < 5 &&
+	    (card->gap_count != gap_count || new_root_id != root_id))
+		do_reset = 1;
+
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	if (do_reset) {
+		fw_notify("phy config: card %d, new root=%x, gap_count=%d\n",
+			  card->index, new_root_id, gap_count);
+		fw_send_phy_config(card, new_root_id, generation, gap_count);
+		fw_core_initiate_bus_reset(card, 1);
+	}
+}
+
+static void
+flush_timer_callback(unsigned long data)
+{
+	struct fw_card *card = (struct fw_card *)data;
+
+	fw_flush_transactions(card);
+}
+
+void
+fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
+		   struct device *device)
+{
+	static atomic_t index = ATOMIC_INIT(-1);
+
+	kref_init(&card->kref);
+	card->index = atomic_inc_return(&index);
+	card->driver = driver;
+	card->device = device;
+	card->current_tlabel = 0;
+	card->tlabel_mask = 0;
+	card->color = 0;
+
+	INIT_LIST_HEAD(&card->transaction_list);
+	spin_lock_init(&card->lock);
+	setup_timer(&card->flush_timer,
+		    flush_timer_callback, (unsigned long)card);
+
+	card->local_node = NULL;
+
+	INIT_DELAYED_WORK(&card->work, fw_card_bm_work);
+}
+EXPORT_SYMBOL(fw_card_initialize);
+
+int
+fw_card_add(struct fw_card *card,
+	    u32 max_receive, u32 link_speed, u64 guid)
+{
+	u32 *config_rom;
+	size_t length;
+
+	card->max_receive = max_receive;
+	card->link_speed = link_speed;
+	card->guid = guid;
+
+	/* Activate link_on bit and contender bit in our self ID packets.*/
+	if (card->driver->update_phy_reg(card, 4, 0,
+					 PHY_LINK_ACTIVE | PHY_CONTENDER) < 0)
+		return -EIO;
+
+	/*
+	 * The subsystem grabs a reference when the card is added and
+	 * drops it when the driver calls fw_core_remove_card.
+	 */
+	fw_card_get(card);
+
+	mutex_lock(&card_mutex);
+	config_rom = generate_config_rom(card, &length);
+	list_add_tail(&card->link, &card_list);
+	mutex_unlock(&card_mutex);
+
+	return card->driver->enable(card, config_rom, length);
+}
+EXPORT_SYMBOL(fw_card_add);
+
+
+/*
+ * The next few functions implements a dummy driver that use once a
+ * card driver shuts down an fw_card.  This allows the driver to
+ * cleanly unload, as all IO to the card will be handled by the dummy
+ * driver instead of calling into the (possibly) unloaded module.  The
+ * dummy driver just fails all IO.
+ */
+
+static int
+dummy_enable(struct fw_card *card, u32 *config_rom, size_t length)
+{
+	BUG();
+	return -1;
+}
+
+static int
+dummy_update_phy_reg(struct fw_card *card, int address,
+		     int clear_bits, int set_bits)
+{
+	return -ENODEV;
+}
+
+static int
+dummy_set_config_rom(struct fw_card *card,
+		     u32 *config_rom, size_t length)
+{
+	/*
+	 * We take the card out of card_list before setting the dummy
+	 * driver, so this should never get called.
+	 */
+	BUG();
+	return -1;
+}
+
+static void
+dummy_send_request(struct fw_card *card, struct fw_packet *packet)
+{
+	packet->callback(packet, card, -ENODEV);
+}
+
+static void
+dummy_send_response(struct fw_card *card, struct fw_packet *packet)
+{
+	packet->callback(packet, card, -ENODEV);
+}
+
+static int
+dummy_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+{
+	return -ENOENT;
+}
+
+static int
+dummy_enable_phys_dma(struct fw_card *card,
+		      int node_id, int generation)
+{
+	return -ENODEV;
+}
+
+static struct fw_card_driver dummy_driver = {
+	.name            = "dummy",
+	.enable          = dummy_enable,
+	.update_phy_reg  = dummy_update_phy_reg,
+	.set_config_rom  = dummy_set_config_rom,
+	.send_request    = dummy_send_request,
+	.cancel_packet   = dummy_cancel_packet,
+	.send_response   = dummy_send_response,
+	.enable_phys_dma = dummy_enable_phys_dma,
+};
+
+void
+fw_core_remove_card(struct fw_card *card)
+{
+	card->driver->update_phy_reg(card, 4,
+				     PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
+	fw_core_initiate_bus_reset(card, 1);
+
+	mutex_lock(&card_mutex);
+	list_del(&card->link);
+	mutex_unlock(&card_mutex);
+
+	/* Set up the dummy driver. */
+	card->driver = &dummy_driver;
+
+	fw_flush_transactions(card);
+
+	fw_destroy_nodes(card);
+
+	fw_card_put(card);
+}
+EXPORT_SYMBOL(fw_core_remove_card);
+
+struct fw_card *
+fw_card_get(struct fw_card *card)
+{
+	kref_get(&card->kref);
+
+	return card;
+}
+EXPORT_SYMBOL(fw_card_get);
+
+static void
+release_card(struct kref *kref)
+{
+	struct fw_card *card = container_of(kref, struct fw_card, kref);
+
+	kfree(card);
+}
+
+/*
+ * An assumption for fw_card_put() is that the card driver allocates
+ * the fw_card struct with kalloc and that it has been shut down
+ * before the last ref is dropped.
+ */
+void
+fw_card_put(struct fw_card *card)
+{
+	kref_put(&card->kref, release_card);
+}
+EXPORT_SYMBOL(fw_card_put);
+
+int
+fw_core_initiate_bus_reset(struct fw_card *card, int short_reset)
+{
+	int reg = short_reset ? 5 : 1;
+	int bit = short_reset ? PHY_BUS_SHORT_RESET : PHY_BUS_RESET;
+
+	return card->driver->update_phy_reg(card, reg, 0, bit);
+}
+EXPORT_SYMBOL(fw_core_initiate_bus_reset);
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
new file mode 100644
index 0000000..0fa5bd5
--- /dev/null
+++ b/drivers/firewire/fw-cdev.c
@@ -0,0 +1,961 @@
+/*
+ * Char device for device raw access
+ *
+ * Copyright (C) 2005-2007  Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/vmalloc.h>
+#include <linux/poll.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/idr.h>
+#include <linux/compat.h>
+#include <linux/firewire-cdev.h>
+#include <asm/uaccess.h>
+#include "fw-transaction.h"
+#include "fw-topology.h"
+#include "fw-device.h"
+
+struct client;
+struct client_resource {
+	struct list_head link;
+	void (*release)(struct client *client, struct client_resource *r);
+	u32 handle;
+};
+
+/*
+ * dequeue_event() just kfree()'s the event, so the event has to be
+ * the first field in the struct.
+ */
+
+struct event {
+	struct { void *data; size_t size; } v[2];
+	struct list_head link;
+};
+
+struct bus_reset {
+	struct event event;
+	struct fw_cdev_event_bus_reset reset;
+};
+
+struct response {
+	struct event event;
+	struct fw_transaction transaction;
+	struct client *client;
+	struct client_resource resource;
+	struct fw_cdev_event_response response;
+};
+
+struct iso_interrupt {
+	struct event event;
+	struct fw_cdev_event_iso_interrupt interrupt;
+};
+
+struct client {
+	u32 version;
+	struct fw_device *device;
+	spinlock_t lock;
+	u32 resource_handle;
+	struct list_head resource_list;
+	struct list_head event_list;
+	wait_queue_head_t wait;
+	u64 bus_reset_closure;
+
+	struct fw_iso_context *iso_context;
+	u64 iso_closure;
+	struct fw_iso_buffer buffer;
+	unsigned long vm_start;
+
+	struct list_head link;
+};
+
+static inline void __user *
+u64_to_uptr(__u64 value)
+{
+	return (void __user *)(unsigned long)value;
+}
+
+static inline __u64
+uptr_to_u64(void __user *ptr)
+{
+	return (__u64)(unsigned long)ptr;
+}
+
+static int fw_device_op_open(struct inode *inode, struct file *file)
+{
+	struct fw_device *device;
+	struct client *client;
+	unsigned long flags;
+
+	device = fw_device_from_devt(inode->i_rdev);
+	if (device == NULL)
+		return -ENODEV;
+
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
+	if (client == NULL)
+		return -ENOMEM;
+
+	client->device = fw_device_get(device);
+	INIT_LIST_HEAD(&client->event_list);
+	INIT_LIST_HEAD(&client->resource_list);
+	spin_lock_init(&client->lock);
+	init_waitqueue_head(&client->wait);
+
+	file->private_data = client;
+
+	spin_lock_irqsave(&device->card->lock, flags);
+	list_add_tail(&client->link, &device->client_list);
+	spin_unlock_irqrestore(&device->card->lock, flags);
+
+	return 0;
+}
+
+static void queue_event(struct client *client, struct event *event,
+			void *data0, size_t size0, void *data1, size_t size1)
+{
+	unsigned long flags;
+
+	event->v[0].data = data0;
+	event->v[0].size = size0;
+	event->v[1].data = data1;
+	event->v[1].size = size1;
+
+	spin_lock_irqsave(&client->lock, flags);
+
+	list_add_tail(&event->link, &client->event_list);
+	wake_up_interruptible(&client->wait);
+
+	spin_unlock_irqrestore(&client->lock, flags);
+}
+
+static int
+dequeue_event(struct client *client, char __user *buffer, size_t count)
+{
+	unsigned long flags;
+	struct event *event;
+	size_t size, total;
+	int i, retval;
+
+	retval = wait_event_interruptible(client->wait,
+					  !list_empty(&client->event_list) ||
+					  fw_device_is_shutdown(client->device));
+	if (retval < 0)
+		return retval;
+
+	if (list_empty(&client->event_list) &&
+		       fw_device_is_shutdown(client->device))
+		return -ENODEV;
+
+	spin_lock_irqsave(&client->lock, flags);
+	event = container_of(client->event_list.next, struct event, link);
+	list_del(&event->link);
+	spin_unlock_irqrestore(&client->lock, flags);
+
+	total = 0;
+	for (i = 0; i < ARRAY_SIZE(event->v) && total < count; i++) {
+		size = min(event->v[i].size, count - total);
+		if (copy_to_user(buffer + total, event->v[i].data, size)) {
+			retval = -EFAULT;
+			goto out;
+		}
+		total += size;
+	}
+	retval = total;
+
+ out:
+	kfree(event);
+
+	return retval;
+}
+
+static ssize_t
+fw_device_op_read(struct file *file,
+		  char __user *buffer, size_t count, loff_t *offset)
+{
+	struct client *client = file->private_data;
+
+	return dequeue_event(client, buffer, count);
+}
+
+static void
+fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
+		     struct client *client)
+{
+	struct fw_card *card = client->device->card;
+
+	event->closure	     = client->bus_reset_closure;
+	event->type          = FW_CDEV_EVENT_BUS_RESET;
+	event->node_id       = client->device->node_id;
+	event->local_node_id = card->local_node->node_id;
+	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
+	event->irm_node_id   = card->irm_node->node_id;
+	event->root_node_id  = card->root_node->node_id;
+	event->generation    = card->generation;
+}
+
+static void
+for_each_client(struct fw_device *device,
+		void (*callback)(struct client *client))
+{
+	struct fw_card *card = device->card;
+	struct client *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	list_for_each_entry(c, &device->client_list, link)
+		callback(c);
+
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+
+static void
+queue_bus_reset_event(struct client *client)
+{
+	struct bus_reset *bus_reset;
+
+	bus_reset = kzalloc(sizeof(*bus_reset), GFP_ATOMIC);
+	if (bus_reset == NULL) {
+		fw_notify("Out of memory when allocating bus reset event\n");
+		return;
+	}
+
+	fill_bus_reset_event(&bus_reset->reset, client);
+
+	queue_event(client, &bus_reset->event,
+		    &bus_reset->reset, sizeof(bus_reset->reset), NULL, 0);
+}
+
+void fw_device_cdev_update(struct fw_device *device)
+{
+	for_each_client(device, queue_bus_reset_event);
+}
+
+static void wake_up_client(struct client *client)
+{
+	wake_up_interruptible(&client->wait);
+}
+
+void fw_device_cdev_remove(struct fw_device *device)
+{
+	for_each_client(device, wake_up_client);
+}
+
+static int ioctl_get_info(struct client *client, void *buffer)
+{
+	struct fw_cdev_get_info *get_info = buffer;
+	struct fw_cdev_event_bus_reset bus_reset;
+
+	client->version = get_info->version;
+	get_info->version = FW_CDEV_VERSION;
+
+	if (get_info->rom != 0) {
+		void __user *uptr = u64_to_uptr(get_info->rom);
+		size_t want = get_info->rom_length;
+		size_t have = client->device->config_rom_length * 4;
+
+		if (copy_to_user(uptr, client->device->config_rom,
+				 min(want, have)))
+			return -EFAULT;
+	}
+	get_info->rom_length = client->device->config_rom_length * 4;
+
+	client->bus_reset_closure = get_info->bus_reset_closure;
+	if (get_info->bus_reset != 0) {
+		void __user *uptr = u64_to_uptr(get_info->bus_reset);
+
+		fill_bus_reset_event(&bus_reset, client);
+		if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset)))
+			return -EFAULT;
+	}
+
+	get_info->card = client->device->card->index;
+
+	return 0;
+}
+
+static void
+add_client_resource(struct client *client, struct client_resource *resource)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&client->lock, flags);
+	list_add_tail(&resource->link, &client->resource_list);
+	resource->handle = client->resource_handle++;
+	spin_unlock_irqrestore(&client->lock, flags);
+}
+
+static int
+release_client_resource(struct client *client, u32 handle,
+			struct client_resource **resource)
+{
+	struct client_resource *r;
+	unsigned long flags;
+
+	spin_lock_irqsave(&client->lock, flags);
+	list_for_each_entry(r, &client->resource_list, link) {
+		if (r->handle == handle) {
+			list_del(&r->link);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&client->lock, flags);
+
+	if (&r->link == &client->resource_list)
+		return -EINVAL;
+
+	if (resource)
+		*resource = r;
+	else
+		r->release(client, r);
+
+	return 0;
+}
+
+static void
+release_transaction(struct client *client, struct client_resource *resource)
+{
+	struct response *response =
+		container_of(resource, struct response, resource);
+
+	fw_cancel_transaction(client->device->card, &response->transaction);
+}
+
+static void
+complete_transaction(struct fw_card *card, int rcode,
+		     void *payload, size_t length, void *data)
+{
+	struct response *response = data;
+	struct client *client = response->client;
+	unsigned long flags;
+
+	if (length < response->response.length)
+		response->response.length = length;
+	if (rcode == RCODE_COMPLETE)
+		memcpy(response->response.data, payload,
+		       response->response.length);
+
+	spin_lock_irqsave(&client->lock, flags);
+	list_del(&response->resource.link);
+	spin_unlock_irqrestore(&client->lock, flags);
+
+	response->response.type   = FW_CDEV_EVENT_RESPONSE;
+	response->response.rcode  = rcode;
+	queue_event(client, &response->event,
+		    &response->response, sizeof(response->response),
+		    response->response.data, response->response.length);
+}
+
+static ssize_t ioctl_send_request(struct client *client, void *buffer)
+{
+	struct fw_device *device = client->device;
+	struct fw_cdev_send_request *request = buffer;
+	struct response *response;
+
+	/* What is the biggest size we'll accept, really? */
+	if (request->length > 4096)
+		return -EINVAL;
+
+	response = kmalloc(sizeof(*response) + request->length, GFP_KERNEL);
+	if (response == NULL)
+		return -ENOMEM;
+
+	response->client = client;
+	response->response.length = request->length;
+	response->response.closure = request->closure;
+
+	if (request->data &&
+	    copy_from_user(response->response.data,
+			   u64_to_uptr(request->data), request->length)) {
+		kfree(response);
+		return -EFAULT;
+	}
+
+	response->resource.release = release_transaction;
+	add_client_resource(client, &response->resource);
+
+	fw_send_request(device->card, &response->transaction,
+			request->tcode & 0x1f,
+			device->node->node_id,
+			request->generation,
+			device->node->max_speed,
+			request->offset,
+			response->response.data, request->length,
+			complete_transaction, response);
+
+	if (request->data)
+		return sizeof(request) + request->length;
+	else
+		return sizeof(request);
+}
+
+struct address_handler {
+	struct fw_address_handler handler;
+	__u64 closure;
+	struct client *client;
+	struct client_resource resource;
+};
+
+struct request {
+	struct fw_request *request;
+	void *data;
+	size_t length;
+	struct client_resource resource;
+};
+
+struct request_event {
+	struct event event;
+	struct fw_cdev_event_request request;
+};
+
+static void
+release_request(struct client *client, struct client_resource *resource)
+{
+	struct request *request =
+		container_of(resource, struct request, resource);
+
+	fw_send_response(client->device->card, request->request,
+			 RCODE_CONFLICT_ERROR);
+	kfree(request);
+}
+
+static void
+handle_request(struct fw_card *card, struct fw_request *r,
+	       int tcode, int destination, int source,
+	       int generation, int speed,
+	       unsigned long long offset,
+	       void *payload, size_t length, void *callback_data)
+{
+	struct address_handler *handler = callback_data;
+	struct request *request;
+	struct request_event *e;
+	struct client *client = handler->client;
+
+	request = kmalloc(sizeof(*request), GFP_ATOMIC);
+	e = kmalloc(sizeof(*e), GFP_ATOMIC);
+	if (request == NULL || e == NULL) {
+		kfree(request);
+		kfree(e);
+		fw_send_response(card, r, RCODE_CONFLICT_ERROR);
+		return;
+	}
+
+	request->request = r;
+	request->data    = payload;
+	request->length  = length;
+
+	request->resource.release = release_request;
+	add_client_resource(client, &request->resource);
+
+	e->request.type    = FW_CDEV_EVENT_REQUEST;
+	e->request.tcode   = tcode;
+	e->request.offset  = offset;
+	e->request.length  = length;
+	e->request.handle  = request->resource.handle;
+	e->request.closure = handler->closure;
+
+	queue_event(client, &e->event,
+		    &e->request, sizeof(e->request), payload, length);
+}
+
+static void
+release_address_handler(struct client *client,
+			struct client_resource *resource)
+{
+	struct address_handler *handler =
+		container_of(resource, struct address_handler, resource);
+
+	fw_core_remove_address_handler(&handler->handler);
+	kfree(handler);
+}
+
+static int ioctl_allocate(struct client *client, void *buffer)
+{
+	struct fw_cdev_allocate *request = buffer;
+	struct address_handler *handler;
+	struct fw_address_region region;
+
+	handler = kmalloc(sizeof(*handler), GFP_KERNEL);
+	if (handler == NULL)
+		return -ENOMEM;
+
+	region.start = request->offset;
+	region.end = request->offset + request->length;
+	handler->handler.length = request->length;
+	handler->handler.address_callback = handle_request;
+	handler->handler.callback_data = handler;
+	handler->closure = request->closure;
+	handler->client = client;
+
+	if (fw_core_add_address_handler(&handler->handler, &region) < 0) {
+		kfree(handler);
+		return -EBUSY;
+	}
+
+	handler->resource.release = release_address_handler;
+	add_client_resource(client, &handler->resource);
+	request->handle = handler->resource.handle;
+
+	return 0;
+}
+
+static int ioctl_deallocate(struct client *client, void *buffer)
+{
+	struct fw_cdev_deallocate *request = buffer;
+
+	return release_client_resource(client, request->handle, NULL);
+}
+
+static int ioctl_send_response(struct client *client, void *buffer)
+{
+	struct fw_cdev_send_response *request = buffer;
+	struct client_resource *resource;
+	struct request *r;
+
+	if (release_client_resource(client, request->handle, &resource) < 0)
+		return -EINVAL;
+	r = container_of(resource, struct request, resource);
+	if (request->length < r->length)
+		r->length = request->length;
+	if (copy_from_user(r->data, u64_to_uptr(request->data), r->length))
+		return -EFAULT;
+
+	fw_send_response(client->device->card, r->request, request->rcode);
+	kfree(r);
+
+	return 0;
+}
+
+static int ioctl_initiate_bus_reset(struct client *client, void *buffer)
+{
+	struct fw_cdev_initiate_bus_reset *request = buffer;
+	int short_reset;
+
+	short_reset = (request->type == FW_CDEV_SHORT_RESET);
+
+	return fw_core_initiate_bus_reset(client->device->card, short_reset);
+}
+
+struct descriptor {
+	struct fw_descriptor d;
+	struct client_resource resource;
+	u32 data[0];
+};
+
+static void release_descriptor(struct client *client,
+			       struct client_resource *resource)
+{
+	struct descriptor *descriptor =
+		container_of(resource, struct descriptor, resource);
+
+	fw_core_remove_descriptor(&descriptor->d);
+	kfree(descriptor);
+}
+
+static int ioctl_add_descriptor(struct client *client, void *buffer)
+{
+	struct fw_cdev_add_descriptor *request = buffer;
+	struct descriptor *descriptor;
+	int retval;
+
+	if (request->length > 256)
+		return -EINVAL;
+
+	descriptor =
+		kmalloc(sizeof(*descriptor) + request->length * 4, GFP_KERNEL);
+	if (descriptor == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(descriptor->data,
+			   u64_to_uptr(request->data), request->length * 4)) {
+		kfree(descriptor);
+		return -EFAULT;
+	}
+
+	descriptor->d.length = request->length;
+	descriptor->d.immediate = request->immediate;
+	descriptor->d.key = request->key;
+	descriptor->d.data = descriptor->data;
+
+	retval = fw_core_add_descriptor(&descriptor->d);
+	if (retval < 0) {
+		kfree(descriptor);
+		return retval;
+	}
+
+	descriptor->resource.release = release_descriptor;
+	add_client_resource(client, &descriptor->resource);
+	request->handle = descriptor->resource.handle;
+
+	return 0;
+}
+
+static int ioctl_remove_descriptor(struct client *client, void *buffer)
+{
+	struct fw_cdev_remove_descriptor *request = buffer;
+
+	return release_client_resource(client, request->handle, NULL);
+}
+
+static void
+iso_callback(struct fw_iso_context *context, u32 cycle,
+	     size_t header_length, void *header, void *data)
+{
+	struct client *client = data;
+	struct iso_interrupt *interrupt;
+
+	interrupt = kzalloc(sizeof(*interrupt) + header_length, GFP_ATOMIC);
+	if (interrupt == NULL)
+		return;
+
+	interrupt->interrupt.type      = FW_CDEV_EVENT_ISO_INTERRUPT;
+	interrupt->interrupt.closure   = client->iso_closure;
+	interrupt->interrupt.cycle     = cycle;
+	interrupt->interrupt.header_length = header_length;
+	memcpy(interrupt->interrupt.header, header, header_length);
+	queue_event(client, &interrupt->event,
+		    &interrupt->interrupt,
+		    sizeof(interrupt->interrupt) + header_length, NULL, 0);
+}
+
+static int ioctl_create_iso_context(struct client *client, void *buffer)
+{
+	struct fw_cdev_create_iso_context *request = buffer;
+
+	if (request->channel > 63)
+		return -EINVAL;
+
+	switch (request->type) {
+	case FW_ISO_CONTEXT_RECEIVE:
+		if (request->header_size < 4 || (request->header_size & 3))
+			return -EINVAL;
+
+		break;
+
+	case FW_ISO_CONTEXT_TRANSMIT:
+		if (request->speed > SCODE_3200)
+			return -EINVAL;
+
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	client->iso_closure = request->closure;
+	client->iso_context = fw_iso_context_create(client->device->card,
+						    request->type,
+						    request->channel,
+						    request->speed,
+						    request->header_size,
+						    iso_callback, client);
+	if (IS_ERR(client->iso_context))
+		return PTR_ERR(client->iso_context);
+
+	/* We only support one context at this time. */
+	request->handle = 0;
+
+	return 0;
+}
+
+static int ioctl_queue_iso(struct client *client, void *buffer)
+{
+	struct fw_cdev_queue_iso *request = buffer;
+	struct fw_cdev_iso_packet __user *p, *end, *next;
+	struct fw_iso_context *ctx = client->iso_context;
+	unsigned long payload, buffer_end, header_length;
+	int count;
+	struct {
+		struct fw_iso_packet packet;
+		u8 header[256];
+	} u;
+
+	if (ctx == NULL || request->handle != 0)
+		return -EINVAL;
+
+	/*
+	 * If the user passes a non-NULL data pointer, has mmap()'ed
+	 * the iso buffer, and the pointer points inside the buffer,
+	 * we setup the payload pointers accordingly.  Otherwise we
+	 * set them both to 0, which will still let packets with
+	 * payload_length == 0 through.  In other words, if no packets
+	 * use the indirect payload, the iso buffer need not be mapped
+	 * and the request->data pointer is ignored.
+	 */
+
+	payload = (unsigned long)request->data - client->vm_start;
+	buffer_end = client->buffer.page_count << PAGE_SHIFT;
+	if (request->data == 0 || client->buffer.pages == NULL ||
+	    payload >= buffer_end) {
+		payload = 0;
+		buffer_end = 0;
+	}
+
+	if (!access_ok(VERIFY_READ, request->packets, request->size))
+		return -EFAULT;
+
+	p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets);
+	end = (void __user *)p + request->size;
+	count = 0;
+	while (p < end) {
+		if (__copy_from_user(&u.packet, p, sizeof(*p)))
+			return -EFAULT;
+
+		if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) {
+			header_length = u.packet.header_length;
+		} else {
+			/*
+			 * We require that header_length is a multiple of
+			 * the fixed header size, ctx->header_size.
+			 */
+			if (ctx->header_size == 0) {
+				if (u.packet.header_length > 0)
+					return -EINVAL;
+			} else if (u.packet.header_length % ctx->header_size != 0) {
+				return -EINVAL;
+			}
+			header_length = 0;
+		}
+
+		next = (struct fw_cdev_iso_packet __user *)
+			&p->header[header_length / 4];
+		if (next > end)
+			return -EINVAL;
+		if (__copy_from_user
+		    (u.packet.header, p->header, header_length))
+			return -EFAULT;
+		if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT &&
+		    u.packet.header_length + u.packet.payload_length > 0)
+			return -EINVAL;
+		if (payload + u.packet.payload_length > buffer_end)
+			return -EINVAL;
+
+		if (fw_iso_context_queue(ctx, &u.packet,
+					 &client->buffer, payload))
+			break;
+
+		p = next;
+		payload += u.packet.payload_length;
+		count++;
+	}
+
+	request->size    -= uptr_to_u64(p) - request->packets;
+	request->packets  = uptr_to_u64(p);
+	request->data     = client->vm_start + payload;
+
+	return count;
+}
+
+static int ioctl_start_iso(struct client *client, void *buffer)
+{
+	struct fw_cdev_start_iso *request = buffer;
+
+	if (request->handle != 0)
+		return -EINVAL;
+	if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) {
+		if (request->tags == 0 || request->tags > 15)
+			return -EINVAL;
+
+		if (request->sync > 15)
+			return -EINVAL;
+	}
+
+	return fw_iso_context_start(client->iso_context, request->cycle,
+				    request->sync, request->tags);
+}
+
+static int ioctl_stop_iso(struct client *client, void *buffer)
+{
+	struct fw_cdev_stop_iso *request = buffer;
+
+	if (request->handle != 0)
+		return -EINVAL;
+
+	return fw_iso_context_stop(client->iso_context);
+}
+
+static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
+	ioctl_get_info,
+	ioctl_send_request,
+	ioctl_allocate,
+	ioctl_deallocate,
+	ioctl_send_response,
+	ioctl_initiate_bus_reset,
+	ioctl_add_descriptor,
+	ioctl_remove_descriptor,
+	ioctl_create_iso_context,
+	ioctl_queue_iso,
+	ioctl_start_iso,
+	ioctl_stop_iso,
+};
+
+static int
+dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg)
+{
+	char buffer[256];
+	int retval;
+
+	if (_IOC_TYPE(cmd) != '#' ||
+	    _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers))
+		return -EINVAL;
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
+		    copy_from_user(buffer, arg, _IOC_SIZE(cmd)))
+			return -EFAULT;
+	}
+
+	retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer);
+	if (retval < 0)
+		return retval;
+
+	if (_IOC_DIR(cmd) & _IOC_READ) {
+		if (_IOC_SIZE(cmd) > sizeof(buffer) ||
+		    copy_to_user(arg, buffer, _IOC_SIZE(cmd)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static long
+fw_device_op_ioctl(struct file *file,
+		   unsigned int cmd, unsigned long arg)
+{
+	struct client *client = file->private_data;
+
+	return dispatch_ioctl(client, cmd, (void __user *) arg);
+}
+
+#ifdef CONFIG_COMPAT
+static long
+fw_device_op_compat_ioctl(struct file *file,
+			  unsigned int cmd, unsigned long arg)
+{
+	struct client *client = file->private_data;
+
+	return dispatch_ioctl(client, cmd, compat_ptr(arg));
+}
+#endif
+
+static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct client *client = file->private_data;
+	enum dma_data_direction direction;
+	unsigned long size;
+	int page_count, retval;
+
+	/* FIXME: We could support multiple buffers, but we don't. */
+	if (client->buffer.pages != NULL)
+		return -EBUSY;
+
+	if (!(vma->vm_flags & VM_SHARED))
+		return -EINVAL;
+
+	if (vma->vm_start & ~PAGE_MASK)
+		return -EINVAL;
+
+	client->vm_start = vma->vm_start;
+	size = vma->vm_end - vma->vm_start;
+	page_count = size >> PAGE_SHIFT;
+	if (size & ~PAGE_MASK)
+		return -EINVAL;
+
+	if (vma->vm_flags & VM_WRITE)
+		direction = DMA_TO_DEVICE;
+	else
+		direction = DMA_FROM_DEVICE;
+
+	retval = fw_iso_buffer_init(&client->buffer, client->device->card,
+				    page_count, direction);
+	if (retval < 0)
+		return retval;
+
+	retval = fw_iso_buffer_map(&client->buffer, vma);
+	if (retval < 0)
+		fw_iso_buffer_destroy(&client->buffer, client->device->card);
+
+	return retval;
+}
+
+static int fw_device_op_release(struct inode *inode, struct file *file)
+{
+	struct client *client = file->private_data;
+	struct event *e, *next_e;
+	struct client_resource *r, *next_r;
+	unsigned long flags;
+
+	if (client->buffer.pages)
+		fw_iso_buffer_destroy(&client->buffer, client->device->card);
+
+	if (client->iso_context)
+		fw_iso_context_destroy(client->iso_context);
+
+	list_for_each_entry_safe(r, next_r, &client->resource_list, link)
+		r->release(client, r);
+
+	/*
+	 * FIXME: We should wait for the async tasklets to stop
+	 * running before freeing the memory.
+	 */
+
+	list_for_each_entry_safe(e, next_e, &client->event_list, link)
+		kfree(e);
+
+	spin_lock_irqsave(&client->device->card->lock, flags);
+	list_del(&client->link);
+	spin_unlock_irqrestore(&client->device->card->lock, flags);
+
+	fw_device_put(client->device);
+	kfree(client);
+
+	return 0;
+}
+
+static unsigned int fw_device_op_poll(struct file *file, poll_table * pt)
+{
+	struct client *client = file->private_data;
+	unsigned int mask = 0;
+
+	poll_wait(file, &client->wait, pt);
+
+	if (fw_device_is_shutdown(client->device))
+		mask |= POLLHUP | POLLERR;
+	if (!list_empty(&client->event_list))
+		mask |= POLLIN | POLLRDNORM;
+
+	return mask;
+}
+
+const struct file_operations fw_device_ops = {
+	.owner		= THIS_MODULE,
+	.open		= fw_device_op_open,
+	.read		= fw_device_op_read,
+	.unlocked_ioctl	= fw_device_op_ioctl,
+	.poll		= fw_device_op_poll,
+	.release	= fw_device_op_release,
+	.mmap		= fw_device_op_mmap,
+
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= fw_device_op_compat_ioctl,
+#endif
+};
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
new file mode 100644
index 0000000..c1ce465
--- /dev/null
+++ b/drivers/firewire/fw-device.c
@@ -0,0 +1,813 @@
+/*
+ * Device probing and sysfs code.
+ *
+ * Copyright (C) 2005-2006  Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include <linux/kthread.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/rwsem.h>
+#include <asm/semaphore.h>
+#include <linux/ctype.h>
+#include "fw-transaction.h"
+#include "fw-topology.h"
+#include "fw-device.h"
+
+void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 * p)
+{
+	ci->p = p + 1;
+	ci->end = ci->p + (p[0] >> 16);
+}
+EXPORT_SYMBOL(fw_csr_iterator_init);
+
+int fw_csr_iterator_next(struct fw_csr_iterator *ci, int *key, int *value)
+{
+	*key = *ci->p >> 24;
+	*value = *ci->p & 0xffffff;
+
+	return ci->p++ < ci->end;
+}
+EXPORT_SYMBOL(fw_csr_iterator_next);
+
+static int is_fw_unit(struct device *dev);
+
+static int match_unit_directory(u32 * directory, const struct fw_device_id *id)
+{
+	struct fw_csr_iterator ci;
+	int key, value, match;
+
+	match = 0;
+	fw_csr_iterator_init(&ci, directory);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		if (key == CSR_VENDOR && value == id->vendor)
+			match |= FW_MATCH_VENDOR;
+		if (key == CSR_MODEL && value == id->model)
+			match |= FW_MATCH_MODEL;
+		if (key == CSR_SPECIFIER_ID && value == id->specifier_id)
+			match |= FW_MATCH_SPECIFIER_ID;
+		if (key == CSR_VERSION && value == id->version)
+			match |= FW_MATCH_VERSION;
+	}
+
+	return (match & id->match_flags) == id->match_flags;
+}
+
+static int fw_unit_match(struct device *dev, struct device_driver *drv)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_driver *driver = fw_driver(drv);
+	int i;
+
+	/* We only allow binding to fw_units. */
+	if (!is_fw_unit(dev))
+		return 0;
+
+	for (i = 0; driver->id_table[i].match_flags != 0; i++) {
+		if (match_unit_directory(unit->directory, &driver->id_table[i]))
+			return 1;
+	}
+
+	return 0;
+}
+
+static int get_modalias(struct fw_unit *unit, char *buffer, size_t buffer_size)
+{
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct fw_csr_iterator ci;
+
+	int key, value;
+	int vendor = 0;
+	int model = 0;
+	int specifier_id = 0;
+	int version = 0;
+
+	fw_csr_iterator_init(&ci, &device->config_rom[5]);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		switch (key) {
+		case CSR_VENDOR:
+			vendor = value;
+			break;
+		case CSR_MODEL:
+			model = value;
+			break;
+		}
+	}
+
+	fw_csr_iterator_init(&ci, unit->directory);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		switch (key) {
+		case CSR_SPECIFIER_ID:
+			specifier_id = value;
+			break;
+		case CSR_VERSION:
+			version = value;
+			break;
+		}
+	}
+
+	return snprintf(buffer, buffer_size,
+			"ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
+			vendor, model, specifier_id, version);
+}
+
+static int
+fw_unit_uevent(struct device *dev, char **envp, int num_envp,
+	       char *buffer, int buffer_size)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	char modalias[64];
+	int length = 0;
+	int i = 0;
+
+	get_modalias(unit, modalias, sizeof(modalias));
+
+	if (add_uevent_var(envp, num_envp, &i,
+			   buffer, buffer_size, &length,
+			   "MODALIAS=%s", modalias))
+		return -ENOMEM;
+
+	envp[i] = NULL;
+
+	return 0;
+}
+
+struct bus_type fw_bus_type = {
+	.name = "firewire",
+	.match = fw_unit_match,
+};
+EXPORT_SYMBOL(fw_bus_type);
+
+struct fw_device *fw_device_get(struct fw_device *device)
+{
+	get_device(&device->device);
+
+	return device;
+}
+
+void fw_device_put(struct fw_device *device)
+{
+	put_device(&device->device);
+}
+
+static void fw_device_release(struct device *dev)
+{
+	struct fw_device *device = fw_device(dev);
+	unsigned long flags;
+
+	/*
+	 * Take the card lock so we don't set this to NULL while a
+	 * FW_NODE_UPDATED callback is being handled.
+	 */
+	spin_lock_irqsave(&device->card->lock, flags);
+	device->node->data = NULL;
+	spin_unlock_irqrestore(&device->card->lock, flags);
+
+	fw_node_put(device->node);
+	fw_card_put(device->card);
+	kfree(device->config_rom);
+	kfree(device);
+}
+
+int fw_device_enable_phys_dma(struct fw_device *device)
+{
+	return device->card->driver->enable_phys_dma(device->card,
+						     device->node_id,
+						     device->generation);
+}
+EXPORT_SYMBOL(fw_device_enable_phys_dma);
+
+struct config_rom_attribute {
+	struct device_attribute attr;
+	u32 key;
+};
+
+static ssize_t
+show_immediate(struct device *dev, struct device_attribute *dattr, char *buf)
+{
+	struct config_rom_attribute *attr =
+		container_of(dattr, struct config_rom_attribute, attr);
+	struct fw_csr_iterator ci;
+	u32 *dir;
+	int key, value;
+
+	if (is_fw_unit(dev))
+		dir = fw_unit(dev)->directory;
+	else
+		dir = fw_device(dev)->config_rom + 5;
+
+	fw_csr_iterator_init(&ci, dir);
+	while (fw_csr_iterator_next(&ci, &key, &value))
+		if (attr->key == key)
+			return snprintf(buf, buf ? PAGE_SIZE : 0,
+					"0x%06x\n", value);
+
+	return -ENOENT;
+}
+
+#define IMMEDIATE_ATTR(name, key)				\
+	{ __ATTR(name, S_IRUGO, show_immediate, NULL), key }
+
+static ssize_t
+show_text_leaf(struct device *dev, struct device_attribute *dattr, char *buf)
+{
+	struct config_rom_attribute *attr =
+		container_of(dattr, struct config_rom_attribute, attr);
+	struct fw_csr_iterator ci;
+	u32 *dir, *block = NULL, *p, *end;
+	int length, key, value, last_key = 0;
+	char *b;
+
+	if (is_fw_unit(dev))
+		dir = fw_unit(dev)->directory;
+	else
+		dir = fw_device(dev)->config_rom + 5;
+
+	fw_csr_iterator_init(&ci, dir);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		if (attr->key == last_key &&
+		    key == (CSR_DESCRIPTOR | CSR_LEAF))
+			block = ci.p - 1 + value;
+		last_key = key;
+	}
+
+	if (block == NULL)
+		return -ENOENT;
+
+	length = min(block[0] >> 16, 256U);
+	if (length < 3)
+		return -ENOENT;
+
+	if (block[1] != 0 || block[2] != 0)
+		/* Unknown encoding. */
+		return -ENOENT;
+
+	if (buf == NULL)
+		return length * 4;
+
+	b = buf;
+	end = &block[length + 1];
+	for (p = &block[3]; p < end; p++, b += 4)
+		* (u32 *) b = (__force u32) __cpu_to_be32(*p);
+
+	/* Strip trailing whitespace and add newline. */
+	while (b--, (isspace(*b) || *b == '\0') && b > buf);
+	strcpy(b + 1, "\n");
+
+	return b + 2 - buf;
+}
+
+#define TEXT_LEAF_ATTR(name, key)				\
+	{ __ATTR(name, S_IRUGO, show_text_leaf, NULL), key }
+
+static struct config_rom_attribute config_rom_attributes[] = {
+	IMMEDIATE_ATTR(vendor, CSR_VENDOR),
+	IMMEDIATE_ATTR(hardware_version, CSR_HARDWARE_VERSION),
+	IMMEDIATE_ATTR(specifier_id, CSR_SPECIFIER_ID),
+	IMMEDIATE_ATTR(version, CSR_VERSION),
+	IMMEDIATE_ATTR(model, CSR_MODEL),
+	TEXT_LEAF_ATTR(vendor_name, CSR_VENDOR),
+	TEXT_LEAF_ATTR(model_name, CSR_MODEL),
+	TEXT_LEAF_ATTR(hardware_version_name, CSR_HARDWARE_VERSION),
+};
+
+static void
+init_fw_attribute_group(struct device *dev,
+			struct device_attribute *attrs,
+			struct fw_attribute_group *group)
+{
+	struct device_attribute *attr;
+	int i, j;
+
+	for (j = 0; attrs[j].attr.name != NULL; j++)
+		group->attrs[j] = &attrs[j].attr;
+
+	for (i = 0; i < ARRAY_SIZE(config_rom_attributes); i++) {
+		attr = &config_rom_attributes[i].attr;
+		if (attr->show(dev, attr, NULL) < 0)
+			continue;
+		group->attrs[j++] = &attr->attr;
+	}
+
+	BUG_ON(j >= ARRAY_SIZE(group->attrs));
+	group->attrs[j++] = NULL;
+	group->groups[0] = &group->group;
+	group->groups[1] = NULL;
+	group->group.attrs = group->attrs;
+	dev->groups = group->groups;
+}
+
+static ssize_t
+modalias_show(struct device *dev,
+	      struct device_attribute *attr, char *buf)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	int length;
+
+	length = get_modalias(unit, buf, PAGE_SIZE);
+	strcpy(buf + length, "\n");
+
+	return length + 1;
+}
+
+static ssize_t
+rom_index_show(struct device *dev,
+	       struct device_attribute *attr, char *buf)
+{
+	struct fw_device *device = fw_device(dev->parent);
+	struct fw_unit *unit = fw_unit(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			(int)(unit->directory - device->config_rom));
+}
+
+static struct device_attribute fw_unit_attributes[] = {
+	__ATTR_RO(modalias),
+	__ATTR_RO(rom_index),
+	__ATTR_NULL,
+};
+
+static ssize_t
+config_rom_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fw_device *device = fw_device(dev);
+
+	memcpy(buf, device->config_rom, device->config_rom_length * 4);
+
+	return device->config_rom_length * 4;
+}
+
+static ssize_t
+guid_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct fw_device *device = fw_device(dev);
+	u64 guid;
+
+	guid = ((u64)device->config_rom[3] << 32) | device->config_rom[4];
+
+	return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
+			(unsigned long long)guid);
+}
+
+static struct device_attribute fw_device_attributes[] = {
+	__ATTR_RO(config_rom),
+	__ATTR_RO(guid),
+	__ATTR_NULL,
+};
+
+struct read_quadlet_callback_data {
+	struct completion done;
+	int rcode;
+	u32 data;
+};
+
+static void
+complete_transaction(struct fw_card *card, int rcode,
+		     void *payload, size_t length, void *data)
+{
+	struct read_quadlet_callback_data *callback_data = data;
+
+	if (rcode == RCODE_COMPLETE)
+		callback_data->data = be32_to_cpu(*(__be32 *)payload);
+	callback_data->rcode = rcode;
+	complete(&callback_data->done);
+}
+
+static int read_rom(struct fw_device *device, int index, u32 * data)
+{
+	struct read_quadlet_callback_data callback_data;
+	struct fw_transaction t;
+	u64 offset;
+
+	init_completion(&callback_data.done);
+
+	offset = 0xfffff0000400ULL + index * 4;
+	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+			device->node_id,
+			device->generation, SCODE_100,
+			offset, NULL, 4, complete_transaction, &callback_data);
+
+	wait_for_completion(&callback_data.done);
+
+	*data = callback_data.data;
+
+	return callback_data.rcode;
+}
+
+static int read_bus_info_block(struct fw_device *device)
+{
+	static u32 rom[256];
+	u32 stack[16], sp, key;
+	int i, end, length;
+
+	/* First read the bus info block. */
+	for (i = 0; i < 5; i++) {
+		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+			return -1;
+		/*
+		 * As per IEEE1212 7.2, during power-up, devices can
+		 * reply with a 0 for the first quadlet of the config
+		 * rom to indicate that they are booting (for example,
+		 * if the firmware is on the disk of a external
+		 * harddisk).  In that case we just fail, and the
+		 * retry mechanism will try again later.
+		 */
+		if (i == 0 && rom[i] == 0)
+			return -1;
+	}
+
+	/*
+	 * Now parse the config rom.  The config rom is a recursive
+	 * directory structure so we parse it using a stack of
+	 * references to the blocks that make up the structure.  We
+	 * push a reference to the root directory on the stack to
+	 * start things off.
+	 */
+	length = i;
+	sp = 0;
+	stack[sp++] = 0xc0000005;
+	while (sp > 0) {
+		/*
+		 * Pop the next block reference of the stack.  The
+		 * lower 24 bits is the offset into the config rom,
+		 * the upper 8 bits are the type of the reference the
+		 * block.
+		 */
+		key = stack[--sp];
+		i = key & 0xffffff;
+		if (i >= ARRAY_SIZE(rom))
+			/*
+			 * The reference points outside the standard
+			 * config rom area, something's fishy.
+			 */
+			return -1;
+
+		/* Read header quadlet for the block to get the length. */
+		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+			return -1;
+		end = i + (rom[i] >> 16) + 1;
+		i++;
+		if (end > ARRAY_SIZE(rom))
+			/*
+			 * This block extends outside standard config
+			 * area (and the array we're reading it
+			 * into).  That's broken, so ignore this
+			 * device.
+			 */
+			return -1;
+
+		/*
+		 * Now read in the block.  If this is a directory
+		 * block, check the entries as we read them to see if
+		 * it references another block, and push it in that case.
+		 */
+		while (i < end) {
+			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
+				return -1;
+			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+			    sp < ARRAY_SIZE(stack))
+				stack[sp++] = i + rom[i];
+			i++;
+		}
+		if (length < i)
+			length = i;
+	}
+
+	device->config_rom = kmalloc(length * 4, GFP_KERNEL);
+	if (device->config_rom == NULL)
+		return -1;
+	memcpy(device->config_rom, rom, length * 4);
+	device->config_rom_length = length;
+
+	return 0;
+}
+
+static void fw_unit_release(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+
+	kfree(unit);
+}
+
+static struct device_type fw_unit_type = {
+	.uevent		= fw_unit_uevent,
+	.release	= fw_unit_release,
+};
+
+static int is_fw_unit(struct device *dev)
+{
+	return dev->type == &fw_unit_type;
+}
+
+static void create_units(struct fw_device *device)
+{
+	struct fw_csr_iterator ci;
+	struct fw_unit *unit;
+	int key, value, i;
+
+	i = 0;
+	fw_csr_iterator_init(&ci, &device->config_rom[5]);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		if (key != (CSR_UNIT | CSR_DIRECTORY))
+			continue;
+
+		/*
+		 * Get the address of the unit directory and try to
+		 * match the drivers id_tables against it.
+		 */
+		unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+		if (unit == NULL) {
+			fw_error("failed to allocate memory for unit\n");
+			continue;
+		}
+
+		unit->directory = ci.p + value - 1;
+		unit->device.bus = &fw_bus_type;
+		unit->device.type = &fw_unit_type;
+		unit->device.parent = &device->device;
+		snprintf(unit->device.bus_id, sizeof(unit->device.bus_id),
+			 "%s.%d", device->device.bus_id, i++);
+
+		init_fw_attribute_group(&unit->device,
+					fw_unit_attributes,
+					&unit->attribute_group);
+		if (device_register(&unit->device) < 0)
+			goto skip_unit;
+
+		continue;
+
+	skip_unit:
+		kfree(unit);
+	}
+}
+
+static int shutdown_unit(struct device *device, void *data)
+{
+	device_unregister(device);
+
+	return 0;
+}
+
+static DECLARE_RWSEM(idr_rwsem);
+static DEFINE_IDR(fw_device_idr);
+int fw_cdev_major;
+
+struct fw_device *fw_device_from_devt(dev_t devt)
+{
+	struct fw_device *device;
+
+	down_read(&idr_rwsem);
+	device = idr_find(&fw_device_idr, MINOR(devt));
+	up_read(&idr_rwsem);
+
+	return device;
+}
+
+static void fw_device_shutdown(struct work_struct *work)
+{
+	struct fw_device *device =
+		container_of(work, struct fw_device, work.work);
+	int minor = MINOR(device->device.devt);
+
+	down_write(&idr_rwsem);
+	idr_remove(&fw_device_idr, minor);
+	up_write(&idr_rwsem);
+
+	fw_device_cdev_remove(device);
+	device_for_each_child(&device->device, NULL, shutdown_unit);
+	device_unregister(&device->device);
+}
+
+static struct device_type fw_device_type = {
+	.release	= fw_device_release,
+};
+
+/*
+ * These defines control the retry behavior for reading the config
+ * rom.  It shouldn't be necessary to tweak these; if the device
+ * doesn't respond to a config rom read within 10 seconds, it's not
+ * going to respond at all.  As for the initial delay, a lot of
+ * devices will be able to respond within half a second after bus
+ * reset.  On the other hand, it's not really worth being more
+ * aggressive than that, since it scales pretty well; if 10 devices
+ * are plugged in, they're all getting read within one second.
+ */
+
+#define MAX_RETRIES	10
+#define RETRY_DELAY	(3 * HZ)
+#define INITIAL_DELAY	(HZ / 2)
+
+static void fw_device_init(struct work_struct *work)
+{
+	struct fw_device *device =
+		container_of(work, struct fw_device, work.work);
+	int minor, err;
+
+	/*
+	 * All failure paths here set node->data to NULL, so that we
+	 * don't try to do device_for_each_child() on a kfree()'d
+	 * device.
+	 */
+
+	if (read_bus_info_block(device) < 0) {
+		if (device->config_rom_retries < MAX_RETRIES) {
+			device->config_rom_retries++;
+			schedule_delayed_work(&device->work, RETRY_DELAY);
+		} else {
+			fw_notify("giving up on config rom for node id %x\n",
+				  device->node_id);
+			if (device->node == device->card->root_node)
+				schedule_delayed_work(&device->card->work, 0);
+			fw_device_release(&device->device);
+		}
+		return;
+	}
+
+	err = -ENOMEM;
+	down_write(&idr_rwsem);
+	if (idr_pre_get(&fw_device_idr, GFP_KERNEL))
+		err = idr_get_new(&fw_device_idr, device, &minor);
+	up_write(&idr_rwsem);
+	if (err < 0)
+		goto error;
+
+	device->device.bus = &fw_bus_type;
+	device->device.type = &fw_device_type;
+	device->device.parent = device->card->device;
+	device->device.devt = MKDEV(fw_cdev_major, minor);
+	snprintf(device->device.bus_id, sizeof(device->device.bus_id),
+		 "fw%d", minor);
+
+	init_fw_attribute_group(&device->device,
+				fw_device_attributes,
+				&device->attribute_group);
+	if (device_add(&device->device)) {
+		fw_error("Failed to add device.\n");
+		goto error_with_cdev;
+	}
+
+	create_units(device);
+
+	/*
+	 * Transition the device to running state.  If it got pulled
+	 * out from under us while we did the intialization work, we
+	 * have to shut down the device again here.  Normally, though,
+	 * fw_node_event will be responsible for shutting it down when
+	 * necessary.  We have to use the atomic cmpxchg here to avoid
+	 * racing with the FW_NODE_DESTROYED case in
+	 * fw_node_event().
+	 */
+	if (atomic_cmpxchg(&device->state,
+		    FW_DEVICE_INITIALIZING,
+		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)
+		fw_device_shutdown(&device->work.work);
+	else
+		fw_notify("created new fw device %s (%d config rom retries)\n",
+			  device->device.bus_id, device->config_rom_retries);
+
+	/*
+	 * Reschedule the IRM work if we just finished reading the
+	 * root node config rom.  If this races with a bus reset we
+	 * just end up running the IRM work a couple of extra times -
+	 * pretty harmless.
+	 */
+	if (device->node == device->card->root_node)
+		schedule_delayed_work(&device->card->work, 0);
+
+	return;
+
+ error_with_cdev:
+	down_write(&idr_rwsem);
+	idr_remove(&fw_device_idr, minor);
+	up_write(&idr_rwsem);
+ error:
+	put_device(&device->device);
+}
+
+static int update_unit(struct device *dev, void *data)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_driver *driver = (struct fw_driver *)dev->driver;
+
+	if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) {
+		down(&dev->sem);
+		driver->update(unit);
+		up(&dev->sem);
+	}
+
+	return 0;
+}
+
+static void fw_device_update(struct work_struct *work)
+{
+	struct fw_device *device =
+		container_of(work, struct fw_device, work.work);
+
+	fw_device_cdev_update(device);
+	device_for_each_child(&device->device, NULL, update_unit);
+}
+
+void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+{
+	struct fw_device *device;
+
+	switch (event) {
+	case FW_NODE_CREATED:
+	case FW_NODE_LINK_ON:
+		if (!node->link_on)
+			break;
+
+		device = kzalloc(sizeof(*device), GFP_ATOMIC);
+		if (device == NULL)
+			break;
+
+		/*
+		 * Do minimal intialization of the device here, the
+		 * rest will happen in fw_device_init().  We need the
+		 * card and node so we can read the config rom and we
+		 * need to do device_initialize() now so
+		 * device_for_each_child() in FW_NODE_UPDATED is
+		 * doesn't freak out.
+		 */
+		device_initialize(&device->device);
+		atomic_set(&device->state, FW_DEVICE_INITIALIZING);
+		device->card = fw_card_get(card);
+		device->node = fw_node_get(node);
+		device->node_id = node->node_id;
+		device->generation = card->generation;
+		INIT_LIST_HEAD(&device->client_list);
+
+		/*
+		 * Set the node data to point back to this device so
+		 * FW_NODE_UPDATED callbacks can update the node_id
+		 * and generation for the device.
+		 */
+		node->data = device;
+
+		/*
+		 * Many devices are slow to respond after bus resets,
+		 * especially if they are bus powered and go through
+		 * power-up after getting plugged in.  We schedule the
+		 * first config rom scan half a second after bus reset.
+		 */
+		INIT_DELAYED_WORK(&device->work, fw_device_init);
+		schedule_delayed_work(&device->work, INITIAL_DELAY);
+		break;
+
+	case FW_NODE_UPDATED:
+		if (!node->link_on || node->data == NULL)
+			break;
+
+		device = node->data;
+		device->node_id = node->node_id;
+		device->generation = card->generation;
+		if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
+			PREPARE_DELAYED_WORK(&device->work, fw_device_update);
+			schedule_delayed_work(&device->work, 0);
+		}
+		break;
+
+	case FW_NODE_DESTROYED:
+	case FW_NODE_LINK_OFF:
+		if (!node->data)
+			break;
+
+		/*
+		 * Destroy the device associated with the node.  There
+		 * are two cases here: either the device is fully
+		 * initialized (FW_DEVICE_RUNNING) or we're in the
+		 * process of reading its config rom
+		 * (FW_DEVICE_INITIALIZING).  If it is fully
+		 * initialized we can reuse device->work to schedule a
+		 * full fw_device_shutdown().  If not, there's work
+		 * scheduled to read it's config rom, and we just put
+		 * the device in shutdown state to have that code fail
+		 * to create the device.
+		 */
+		device = node->data;
+		if (atomic_xchg(&device->state,
+				FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) {
+			PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
+			schedule_delayed_work(&device->work, 0);
+		}
+		break;
+	}
+}
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
new file mode 100644
index 0000000..0ba9d64
--- /dev/null
+++ b/drivers/firewire/fw-device.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2005-2006  Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __fw_device_h
+#define __fw_device_h
+
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <asm/atomic.h>
+
+enum fw_device_state {
+	FW_DEVICE_INITIALIZING,
+	FW_DEVICE_RUNNING,
+	FW_DEVICE_SHUTDOWN,
+};
+
+struct fw_attribute_group {
+	struct attribute_group *groups[2];
+	struct attribute_group group;
+	struct attribute *attrs[11];
+};
+
+struct fw_device {
+	atomic_t state;
+	struct fw_node *node;
+	int node_id;
+	int generation;
+	struct fw_card *card;
+	struct device device;
+	struct list_head link;
+	struct list_head client_list;
+	u32 *config_rom;
+	size_t config_rom_length;
+	int config_rom_retries;
+	struct delayed_work work;
+	struct fw_attribute_group attribute_group;
+};
+
+static inline struct fw_device *
+fw_device(struct device *dev)
+{
+	return container_of(dev, struct fw_device, device);
+}
+
+static inline int
+fw_device_is_shutdown(struct fw_device *device)
+{
+	return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN;
+}
+
+struct fw_device *fw_device_get(struct fw_device *device);
+void fw_device_put(struct fw_device *device);
+int fw_device_enable_phys_dma(struct fw_device *device);
+
+void fw_device_cdev_update(struct fw_device *device);
+void fw_device_cdev_remove(struct fw_device *device);
+
+struct fw_device *fw_device_from_devt(dev_t devt);
+extern int fw_cdev_major;
+
+struct fw_unit {
+	struct device device;
+	u32 *directory;
+	struct fw_attribute_group attribute_group;
+};
+
+static inline struct fw_unit *
+fw_unit(struct device *dev)
+{
+	return container_of(dev, struct fw_unit, device);
+}
+
+#define CSR_OFFSET	0x40
+#define CSR_LEAF	0x80
+#define CSR_DIRECTORY	0xc0
+
+#define CSR_DESCRIPTOR		0x01
+#define CSR_VENDOR		0x03
+#define CSR_HARDWARE_VERSION	0x04
+#define CSR_NODE_CAPABILITIES	0x0c
+#define CSR_UNIT		0x11
+#define CSR_SPECIFIER_ID	0x12
+#define CSR_VERSION		0x13
+#define CSR_DEPENDENT_INFO	0x14
+#define CSR_MODEL		0x17
+#define CSR_INSTANCE		0x18
+
+#define SBP2_COMMAND_SET_SPECIFIER	0x38
+#define SBP2_COMMAND_SET		0x39
+#define SBP2_COMMAND_SET_REVISION	0x3b
+#define SBP2_FIRMWARE_REVISION		0x3c
+
+struct fw_csr_iterator {
+	u32 *p;
+	u32 *end;
+};
+
+void fw_csr_iterator_init(struct fw_csr_iterator *ci, u32 *p);
+int fw_csr_iterator_next(struct fw_csr_iterator *ci,
+			 int *key, int *value);
+
+#define FW_MATCH_VENDOR		0x0001
+#define FW_MATCH_MODEL		0x0002
+#define FW_MATCH_SPECIFIER_ID	0x0004
+#define FW_MATCH_VERSION	0x0008
+
+struct fw_device_id {
+	u32 match_flags;
+	u32 vendor;
+	u32 model;
+	u32 specifier_id;
+	u32 version;
+	void *driver_data;
+};
+
+struct fw_driver {
+	struct device_driver driver;
+	/* Called when the parent device sits through a bus reset. */
+	void (*update) (struct fw_unit *unit);
+	const struct fw_device_id *id_table;
+};
+
+static inline struct fw_driver *
+fw_driver(struct device_driver *drv)
+{
+	return container_of(drv, struct fw_driver, driver);
+}
+
+extern const struct file_operations fw_device_ops;
+
+#endif /* __fw_device_h */
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c
new file mode 100644
index 0000000..2b640e9
--- /dev/null
+++ b/drivers/firewire/fw-iso.c
@@ -0,0 +1,163 @@
+/*
+ * Isochronous IO functionality
+ *
+ * Copyright (C) 2006 Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+
+#include "fw-transaction.h"
+#include "fw-topology.h"
+#include "fw-device.h"
+
+int
+fw_iso_buffer_init(struct fw_iso_buffer *buffer, struct fw_card *card,
+		   int page_count, enum dma_data_direction direction)
+{
+	int i, j, retval = -ENOMEM;
+	dma_addr_t address;
+
+	buffer->page_count = page_count;
+	buffer->direction = direction;
+
+	buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]),
+				GFP_KERNEL);
+	if (buffer->pages == NULL)
+		goto out;
+
+	for (i = 0; i < buffer->page_count; i++) {
+		buffer->pages[i] = alloc_page(GFP_KERNEL | GFP_DMA32 | __GFP_ZERO);
+		if (buffer->pages[i] == NULL)
+			goto out_pages;
+
+		address = dma_map_page(card->device, buffer->pages[i],
+				       0, PAGE_SIZE, direction);
+		if (dma_mapping_error(address)) {
+			__free_page(buffer->pages[i]);
+			goto out_pages;
+		}
+		set_page_private(buffer->pages[i], address);
+	}
+
+	return 0;
+
+ out_pages:
+	for (j = 0; j < i; j++) {
+		address = page_private(buffer->pages[j]);
+		dma_unmap_page(card->device, address,
+			       PAGE_SIZE, DMA_TO_DEVICE);
+		__free_page(buffer->pages[j]);
+	}
+	kfree(buffer->pages);
+ out:
+	buffer->pages = NULL;
+	return retval;
+}
+
+int fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma)
+{
+	unsigned long uaddr;
+	int i, retval;
+
+	uaddr = vma->vm_start;
+	for (i = 0; i < buffer->page_count; i++) {
+		retval = vm_insert_page(vma, uaddr, buffer->pages[i]);
+		if (retval)
+			return retval;
+		uaddr += PAGE_SIZE;
+	}
+
+	return 0;
+}
+
+void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer,
+			   struct fw_card *card)
+{
+	int i;
+	dma_addr_t address;
+
+	for (i = 0; i < buffer->page_count; i++) {
+		address = page_private(buffer->pages[i]);
+		dma_unmap_page(card->device, address,
+			       PAGE_SIZE, DMA_TO_DEVICE);
+		__free_page(buffer->pages[i]);
+	}
+
+	kfree(buffer->pages);
+	buffer->pages = NULL;
+}
+
+struct fw_iso_context *
+fw_iso_context_create(struct fw_card *card, int type,
+		      int channel, int speed, size_t header_size,
+		      fw_iso_callback_t callback, void *callback_data)
+{
+	struct fw_iso_context *ctx;
+
+	ctx = card->driver->allocate_iso_context(card, type, header_size);
+	if (IS_ERR(ctx))
+		return ctx;
+
+	ctx->card = card;
+	ctx->type = type;
+	ctx->channel = channel;
+	ctx->speed = speed;
+	ctx->header_size = header_size;
+	ctx->callback = callback;
+	ctx->callback_data = callback_data;
+
+	return ctx;
+}
+EXPORT_SYMBOL(fw_iso_context_create);
+
+void fw_iso_context_destroy(struct fw_iso_context *ctx)
+{
+	struct fw_card *card = ctx->card;
+
+	card->driver->free_iso_context(ctx);
+}
+EXPORT_SYMBOL(fw_iso_context_destroy);
+
+int
+fw_iso_context_start(struct fw_iso_context *ctx, int cycle, int sync, int tags)
+{
+	return ctx->card->driver->start_iso(ctx, cycle, sync, tags);
+}
+EXPORT_SYMBOL(fw_iso_context_start);
+
+int
+fw_iso_context_queue(struct fw_iso_context *ctx,
+		     struct fw_iso_packet *packet,
+		     struct fw_iso_buffer *buffer,
+		     unsigned long payload)
+{
+	struct fw_card *card = ctx->card;
+
+	return card->driver->queue_iso(ctx, packet, buffer, payload);
+}
+EXPORT_SYMBOL(fw_iso_context_queue);
+
+int
+fw_iso_context_stop(struct fw_iso_context *ctx)
+{
+	return ctx->card->driver->stop_iso(ctx);
+}
+EXPORT_SYMBOL(fw_iso_context_stop);
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
new file mode 100644
index 0000000..1f5c704
--- /dev/null
+++ b/drivers/firewire/fw-ohci.c
@@ -0,0 +1,1943 @@
+/*
+ * Driver for OHCI 1394 controllers
+ *
+ * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "fw-transaction.h"
+#include "fw-ohci.h"
+
+#define DESCRIPTOR_OUTPUT_MORE		0
+#define DESCRIPTOR_OUTPUT_LAST		(1 << 12)
+#define DESCRIPTOR_INPUT_MORE		(2 << 12)
+#define DESCRIPTOR_INPUT_LAST		(3 << 12)
+#define DESCRIPTOR_STATUS		(1 << 11)
+#define DESCRIPTOR_KEY_IMMEDIATE	(2 << 8)
+#define DESCRIPTOR_PING			(1 << 7)
+#define DESCRIPTOR_YY			(1 << 6)
+#define DESCRIPTOR_NO_IRQ		(0 << 4)
+#define DESCRIPTOR_IRQ_ERROR		(1 << 4)
+#define DESCRIPTOR_IRQ_ALWAYS		(3 << 4)
+#define DESCRIPTOR_BRANCH_ALWAYS	(3 << 2)
+#define DESCRIPTOR_WAIT			(3 << 0)
+
+struct descriptor {
+	__le16 req_count;
+	__le16 control;
+	__le32 data_address;
+	__le32 branch_address;
+	__le16 res_count;
+	__le16 transfer_status;
+} __attribute__((aligned(16)));
+
+struct db_descriptor {
+	__le16 first_size;
+	__le16 control;
+	__le16 second_req_count;
+	__le16 first_req_count;
+	__le32 branch_address;
+	__le16 second_res_count;
+	__le16 first_res_count;
+	__le32 reserved0;
+	__le32 first_buffer;
+	__le32 second_buffer;
+	__le32 reserved1;
+} __attribute__((aligned(16)));
+
+#define CONTROL_SET(regs)	(regs)
+#define CONTROL_CLEAR(regs)	((regs) + 4)
+#define COMMAND_PTR(regs)	((regs) + 12)
+#define CONTEXT_MATCH(regs)	((regs) + 16)
+
+struct ar_buffer {
+	struct descriptor descriptor;
+	struct ar_buffer *next;
+	__le32 data[0];
+};
+
+struct ar_context {
+	struct fw_ohci *ohci;
+	struct ar_buffer *current_buffer;
+	struct ar_buffer *last_buffer;
+	void *pointer;
+	u32 regs;
+	struct tasklet_struct tasklet;
+};
+
+struct context;
+
+typedef int (*descriptor_callback_t)(struct context *ctx,
+				     struct descriptor *d,
+				     struct descriptor *last);
+struct context {
+	struct fw_ohci *ohci;
+	u32 regs;
+
+	struct descriptor *buffer;
+	dma_addr_t buffer_bus;
+	size_t buffer_size;
+	struct descriptor *head_descriptor;
+	struct descriptor *tail_descriptor;
+	struct descriptor *tail_descriptor_last;
+	struct descriptor *prev_descriptor;
+
+	descriptor_callback_t callback;
+
+	struct tasklet_struct tasklet;
+};
+
+#define IT_HEADER_SY(v)          ((v) <<  0)
+#define IT_HEADER_TCODE(v)       ((v) <<  4)
+#define IT_HEADER_CHANNEL(v)     ((v) <<  8)
+#define IT_HEADER_TAG(v)         ((v) << 14)
+#define IT_HEADER_SPEED(v)       ((v) << 16)
+#define IT_HEADER_DATA_LENGTH(v) ((v) << 16)
+
+struct iso_context {
+	struct fw_iso_context base;
+	struct context context;
+	void *header;
+	size_t header_length;
+};
+
+#define CONFIG_ROM_SIZE 1024
+
+struct fw_ohci {
+	struct fw_card card;
+
+	u32 version;
+	__iomem char *registers;
+	dma_addr_t self_id_bus;
+	__le32 *self_id_cpu;
+	struct tasklet_struct bus_reset_tasklet;
+	int node_id;
+	int generation;
+	int request_generation;
+	u32 bus_seconds;
+
+	/*
+	 * Spinlock for accessing fw_ohci data.  Never call out of
+	 * this driver with this lock held.
+	 */
+	spinlock_t lock;
+	u32 self_id_buffer[512];
+
+	/* Config rom buffers */
+	__be32 *config_rom;
+	dma_addr_t config_rom_bus;
+	__be32 *next_config_rom;
+	dma_addr_t next_config_rom_bus;
+	u32 next_header;
+
+	struct ar_context ar_request_ctx;
+	struct ar_context ar_response_ctx;
+	struct context at_request_ctx;
+	struct context at_response_ctx;
+
+	u32 it_context_mask;
+	struct iso_context *it_context_list;
+	u32 ir_context_mask;
+	struct iso_context *ir_context_list;
+};
+
+static inline struct fw_ohci *fw_ohci(struct fw_card *card)
+{
+	return container_of(card, struct fw_ohci, card);
+}
+
+#define IT_CONTEXT_CYCLE_MATCH_ENABLE	0x80000000
+#define IR_CONTEXT_BUFFER_FILL		0x80000000
+#define IR_CONTEXT_ISOCH_HEADER		0x40000000
+#define IR_CONTEXT_CYCLE_MATCH_ENABLE	0x20000000
+#define IR_CONTEXT_MULTI_CHANNEL_MODE	0x10000000
+#define IR_CONTEXT_DUAL_BUFFER_MODE	0x08000000
+
+#define CONTEXT_RUN	0x8000
+#define CONTEXT_WAKE	0x1000
+#define CONTEXT_DEAD	0x0800
+#define CONTEXT_ACTIVE	0x0400
+
+#define OHCI1394_MAX_AT_REQ_RETRIES	0x2
+#define OHCI1394_MAX_AT_RESP_RETRIES	0x2
+#define OHCI1394_MAX_PHYS_RESP_RETRIES	0x8
+
+#define FW_OHCI_MAJOR			240
+#define OHCI1394_REGISTER_SIZE		0x800
+#define OHCI_LOOP_COUNT			500
+#define OHCI1394_PCI_HCI_Control	0x40
+#define SELF_ID_BUF_SIZE		0x800
+#define OHCI_TCODE_PHY_PACKET		0x0e
+#define OHCI_VERSION_1_1		0x010010
+#define ISO_BUFFER_SIZE			(64 * 1024)
+#define AT_BUFFER_SIZE			4096
+
+static char ohci_driver_name[] = KBUILD_MODNAME;
+
+static inline void reg_write(const struct fw_ohci *ohci, int offset, u32 data)
+{
+	writel(data, ohci->registers + offset);
+}
+
+static inline u32 reg_read(const struct fw_ohci *ohci, int offset)
+{
+	return readl(ohci->registers + offset);
+}
+
+static inline void flush_writes(const struct fw_ohci *ohci)
+{
+	/* Do a dummy read to flush writes. */
+	reg_read(ohci, OHCI1394_Version);
+}
+
+static int
+ohci_update_phy_reg(struct fw_card *card, int addr,
+		    int clear_bits, int set_bits)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	u32 val, old;
+
+	reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr));
+	msleep(2);
+	val = reg_read(ohci, OHCI1394_PhyControl);
+	if ((val & OHCI1394_PhyControl_ReadDone) == 0) {
+		fw_error("failed to set phy reg bits.\n");
+		return -EBUSY;
+	}
+
+	old = OHCI1394_PhyControl_ReadData(val);
+	old = (old & ~clear_bits) | set_bits;
+	reg_write(ohci, OHCI1394_PhyControl,
+		  OHCI1394_PhyControl_Write(addr, old));
+
+	return 0;
+}
+
+static int ar_context_add_page(struct ar_context *ctx)
+{
+	struct device *dev = ctx->ohci->card.device;
+	struct ar_buffer *ab;
+	dma_addr_t ab_bus;
+	size_t offset;
+
+	ab = (struct ar_buffer *) __get_free_page(GFP_ATOMIC);
+	if (ab == NULL)
+		return -ENOMEM;
+
+	ab_bus = dma_map_single(dev, ab, PAGE_SIZE, DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(ab_bus)) {
+		free_page((unsigned long) ab);
+		return -ENOMEM;
+	}
+
+	memset(&ab->descriptor, 0, sizeof(ab->descriptor));
+	ab->descriptor.control        = cpu_to_le16(DESCRIPTOR_INPUT_MORE |
+						    DESCRIPTOR_STATUS |
+						    DESCRIPTOR_BRANCH_ALWAYS);
+	offset = offsetof(struct ar_buffer, data);
+	ab->descriptor.req_count      = cpu_to_le16(PAGE_SIZE - offset);
+	ab->descriptor.data_address   = cpu_to_le32(ab_bus + offset);
+	ab->descriptor.res_count      = cpu_to_le16(PAGE_SIZE - offset);
+	ab->descriptor.branch_address = 0;
+
+	dma_sync_single_for_device(dev, ab_bus, PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+	ctx->last_buffer->descriptor.branch_address = ab_bus | 1;
+	ctx->last_buffer->next = ab;
+	ctx->last_buffer = ab;
+
+	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
+	flush_writes(ctx->ohci);
+
+	return 0;
+}
+
+static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer)
+{
+	struct fw_ohci *ohci = ctx->ohci;
+	struct fw_packet p;
+	u32 status, length, tcode;
+
+	p.header[0] = le32_to_cpu(buffer[0]);
+	p.header[1] = le32_to_cpu(buffer[1]);
+	p.header[2] = le32_to_cpu(buffer[2]);
+
+	tcode = (p.header[0] >> 4) & 0x0f;
+	switch (tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+	case TCODE_READ_QUADLET_RESPONSE:
+		p.header[3] = (__force __u32) buffer[3];
+		p.header_length = 16;
+		p.payload_length = 0;
+		break;
+
+	case TCODE_READ_BLOCK_REQUEST :
+		p.header[3] = le32_to_cpu(buffer[3]);
+		p.header_length = 16;
+		p.payload_length = 0;
+		break;
+
+	case TCODE_WRITE_BLOCK_REQUEST:
+	case TCODE_READ_BLOCK_RESPONSE:
+	case TCODE_LOCK_REQUEST:
+	case TCODE_LOCK_RESPONSE:
+		p.header[3] = le32_to_cpu(buffer[3]);
+		p.header_length = 16;
+		p.payload_length = p.header[3] >> 16;
+		break;
+
+	case TCODE_WRITE_RESPONSE:
+	case TCODE_READ_QUADLET_REQUEST:
+	case OHCI_TCODE_PHY_PACKET:
+		p.header_length = 12;
+		p.payload_length = 0;
+		break;
+	}
+
+	p.payload = (void *) buffer + p.header_length;
+
+	/* FIXME: What to do about evt_* errors? */
+	length = (p.header_length + p.payload_length + 3) / 4;
+	status = le32_to_cpu(buffer[length]);
+
+	p.ack        = ((status >> 16) & 0x1f) - 16;
+	p.speed      = (status >> 21) & 0x7;
+	p.timestamp  = status & 0xffff;
+	p.generation = ohci->request_generation;
+
+	/*
+	 * The OHCI bus reset handler synthesizes a phy packet with
+	 * the new generation number when a bus reset happens (see
+	 * section 8.4.2.3).  This helps us determine when a request
+	 * was received and make sure we send the response in the same
+	 * generation.  We only need this for requests; for responses
+	 * we use the unique tlabel for finding the matching
+	 * request.
+	 */
+
+	if (p.ack + 16 == 0x09)
+		ohci->request_generation = (buffer[2] >> 16) & 0xff;
+	else if (ctx == &ohci->ar_request_ctx)
+		fw_core_handle_request(&ohci->card, &p);
+	else
+		fw_core_handle_response(&ohci->card, &p);
+
+	return buffer + length + 1;
+}
+
+static void ar_context_tasklet(unsigned long data)
+{
+	struct ar_context *ctx = (struct ar_context *)data;
+	struct fw_ohci *ohci = ctx->ohci;
+	struct ar_buffer *ab;
+	struct descriptor *d;
+	void *buffer, *end;
+
+	ab = ctx->current_buffer;
+	d = &ab->descriptor;
+
+	if (d->res_count == 0) {
+		size_t size, rest, offset;
+
+		/*
+		 * This descriptor is finished and we may have a
+		 * packet split across this and the next buffer. We
+		 * reuse the page for reassembling the split packet.
+		 */
+
+		offset = offsetof(struct ar_buffer, data);
+		dma_unmap_single(ohci->card.device,
+				 ab->descriptor.data_address - offset,
+				 PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+		buffer = ab;
+		ab = ab->next;
+		d = &ab->descriptor;
+		size = buffer + PAGE_SIZE - ctx->pointer;
+		rest = le16_to_cpu(d->req_count) - le16_to_cpu(d->res_count);
+		memmove(buffer, ctx->pointer, size);
+		memcpy(buffer + size, ab->data, rest);
+		ctx->current_buffer = ab;
+		ctx->pointer = (void *) ab->data + rest;
+		end = buffer + size + rest;
+
+		while (buffer < end)
+			buffer = handle_ar_packet(ctx, buffer);
+
+		free_page((unsigned long)buffer);
+		ar_context_add_page(ctx);
+	} else {
+		buffer = ctx->pointer;
+		ctx->pointer = end =
+			(void *) ab + PAGE_SIZE - le16_to_cpu(d->res_count);
+
+		while (buffer < end)
+			buffer = handle_ar_packet(ctx, buffer);
+	}
+}
+
+static int
+ar_context_init(struct ar_context *ctx, struct fw_ohci *ohci, u32 regs)
+{
+	struct ar_buffer ab;
+
+	ctx->regs        = regs;
+	ctx->ohci        = ohci;
+	ctx->last_buffer = &ab;
+	tasklet_init(&ctx->tasklet, ar_context_tasklet, (unsigned long)ctx);
+
+	ar_context_add_page(ctx);
+	ar_context_add_page(ctx);
+	ctx->current_buffer = ab.next;
+	ctx->pointer = ctx->current_buffer->data;
+
+	reg_write(ctx->ohci, COMMAND_PTR(ctx->regs), ab.descriptor.branch_address);
+	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN);
+	flush_writes(ctx->ohci);
+
+	return 0;
+}
+
+static void context_tasklet(unsigned long data)
+{
+	struct context *ctx = (struct context *) data;
+	struct fw_ohci *ohci = ctx->ohci;
+	struct descriptor *d, *last;
+	u32 address;
+	int z;
+
+	dma_sync_single_for_cpu(ohci->card.device, ctx->buffer_bus,
+				ctx->buffer_size, DMA_TO_DEVICE);
+
+	d    = ctx->tail_descriptor;
+	last = ctx->tail_descriptor_last;
+
+	while (last->branch_address != 0) {
+		address = le32_to_cpu(last->branch_address);
+		z = address & 0xf;
+		d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d);
+		last = (z == 2) ? d : d + z - 1;
+
+		if (!ctx->callback(ctx, d, last))
+			break;
+
+		ctx->tail_descriptor      = d;
+		ctx->tail_descriptor_last = last;
+	}
+}
+
+static int
+context_init(struct context *ctx, struct fw_ohci *ohci,
+	     size_t buffer_size, u32 regs,
+	     descriptor_callback_t callback)
+{
+	ctx->ohci = ohci;
+	ctx->regs = regs;
+	ctx->buffer_size = buffer_size;
+	ctx->buffer = kmalloc(buffer_size, GFP_KERNEL);
+	if (ctx->buffer == NULL)
+		return -ENOMEM;
+
+	tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx);
+	ctx->callback = callback;
+
+	ctx->buffer_bus =
+		dma_map_single(ohci->card.device, ctx->buffer,
+			       buffer_size, DMA_TO_DEVICE);
+	if (dma_mapping_error(ctx->buffer_bus)) {
+		kfree(ctx->buffer);
+		return -ENOMEM;
+	}
+
+	ctx->head_descriptor      = ctx->buffer;
+	ctx->prev_descriptor      = ctx->buffer;
+	ctx->tail_descriptor      = ctx->buffer;
+	ctx->tail_descriptor_last = ctx->buffer;
+
+	/*
+	 * We put a dummy descriptor in the buffer that has a NULL
+	 * branch address and looks like it's been sent.  That way we
+	 * have a descriptor to append DMA programs to.  Also, the
+	 * ring buffer invariant is that it always has at least one
+	 * element so that head == tail means buffer full.
+	 */
+
+	memset(ctx->head_descriptor, 0, sizeof(*ctx->head_descriptor));
+	ctx->head_descriptor->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
+	ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011);
+	ctx->head_descriptor++;
+
+	return 0;
+}
+
+static void
+context_release(struct context *ctx)
+{
+	struct fw_card *card = &ctx->ohci->card;
+
+	dma_unmap_single(card->device, ctx->buffer_bus,
+			 ctx->buffer_size, DMA_TO_DEVICE);
+	kfree(ctx->buffer);
+}
+
+static struct descriptor *
+context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus)
+{
+	struct descriptor *d, *tail, *end;
+
+	d = ctx->head_descriptor;
+	tail = ctx->tail_descriptor;
+	end = ctx->buffer + ctx->buffer_size / sizeof(*d);
+
+	if (d + z <= tail) {
+		goto has_space;
+	} else if (d > tail && d + z <= end) {
+		goto has_space;
+	} else if (d > tail && ctx->buffer + z <= tail) {
+		d = ctx->buffer;
+		goto has_space;
+	}
+
+	return NULL;
+
+ has_space:
+	memset(d, 0, z * sizeof(*d));
+	*d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d);
+
+	return d;
+}
+
+static void context_run(struct context *ctx, u32 extra)
+{
+	struct fw_ohci *ohci = ctx->ohci;
+
+	reg_write(ohci, COMMAND_PTR(ctx->regs),
+		  le32_to_cpu(ctx->tail_descriptor_last->branch_address));
+	reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0);
+	reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra);
+	flush_writes(ohci);
+}
+
+static void context_append(struct context *ctx,
+			   struct descriptor *d, int z, int extra)
+{
+	dma_addr_t d_bus;
+
+	d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d);
+
+	ctx->head_descriptor = d + z + extra;
+	ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z);
+	ctx->prev_descriptor = z == 2 ? d : d + z - 1;
+
+	dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus,
+				   ctx->buffer_size, DMA_TO_DEVICE);
+
+	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
+	flush_writes(ctx->ohci);
+}
+
+static void context_stop(struct context *ctx)
+{
+	u32 reg;
+	int i;
+
+	reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
+	flush_writes(ctx->ohci);
+
+	for (i = 0; i < 10; i++) {
+		reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
+		if ((reg & CONTEXT_ACTIVE) == 0)
+			break;
+
+		fw_notify("context_stop: still active (0x%08x)\n", reg);
+		msleep(1);
+	}
+}
+
+struct driver_data {
+	struct fw_packet *packet;
+};
+
+/*
+ * This function apppends a packet to the DMA queue for transmission.
+ * Must always be called with the ochi->lock held to ensure proper
+ * generation handling and locking around packet queue manipulation.
+ */
+static int
+at_context_queue_packet(struct context *ctx, struct fw_packet *packet)
+{
+	struct fw_ohci *ohci = ctx->ohci;
+	dma_addr_t d_bus, payload_bus;
+	struct driver_data *driver_data;
+	struct descriptor *d, *last;
+	__le32 *header;
+	int z, tcode;
+	u32 reg;
+
+	d = context_get_descriptors(ctx, 4, &d_bus);
+	if (d == NULL) {
+		packet->ack = RCODE_SEND_ERROR;
+		return -1;
+	}
+
+	d[0].control   = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE);
+	d[0].res_count = cpu_to_le16(packet->timestamp);
+
+	/*
+	 * The DMA format for asyncronous link packets is different
+	 * from the IEEE1394 layout, so shift the fields around
+	 * accordingly.  If header_length is 8, it's a PHY packet, to
+	 * which we need to prepend an extra quadlet.
+	 */
+
+	header = (__le32 *) &d[1];
+	if (packet->header_length > 8) {
+		header[0] = cpu_to_le32((packet->header[0] & 0xffff) |
+					(packet->speed << 16));
+		header[1] = cpu_to_le32((packet->header[1] & 0xffff) |
+					(packet->header[0] & 0xffff0000));
+		header[2] = cpu_to_le32(packet->header[2]);
+
+		tcode = (packet->header[0] >> 4) & 0x0f;
+		if (TCODE_IS_BLOCK_PACKET(tcode))
+			header[3] = cpu_to_le32(packet->header[3]);
+		else
+			header[3] = (__force __le32) packet->header[3];
+
+		d[0].req_count = cpu_to_le16(packet->header_length);
+	} else {
+		header[0] = cpu_to_le32((OHCI1394_phy_tcode << 4) |
+					(packet->speed << 16));
+		header[1] = cpu_to_le32(packet->header[0]);
+		header[2] = cpu_to_le32(packet->header[1]);
+		d[0].req_count = cpu_to_le16(12);
+	}
+
+	driver_data = (struct driver_data *) &d[3];
+	driver_data->packet = packet;
+	packet->driver_data = driver_data;
+	
+	if (packet->payload_length > 0) {
+		payload_bus =
+			dma_map_single(ohci->card.device, packet->payload,
+				       packet->payload_length, DMA_TO_DEVICE);
+		if (dma_mapping_error(payload_bus)) {
+			packet->ack = RCODE_SEND_ERROR;
+			return -1;
+		}
+
+		d[2].req_count    = cpu_to_le16(packet->payload_length);
+		d[2].data_address = cpu_to_le32(payload_bus);
+		last = &d[2];
+		z = 3;
+	} else {
+		last = &d[0];
+		z = 2;
+	}
+
+	last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST |
+				     DESCRIPTOR_IRQ_ALWAYS |
+				     DESCRIPTOR_BRANCH_ALWAYS);
+
+	/* FIXME: Document how the locking works. */
+	if (ohci->generation != packet->generation) {
+		packet->ack = RCODE_GENERATION;
+		return -1;
+	}
+
+	context_append(ctx, d, z, 4 - z);
+
+	/* If the context isn't already running, start it up. */
+	reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
+	if ((reg & CONTEXT_RUN) == 0)
+		context_run(ctx, 0);
+
+	return 0;
+}
+
+static int handle_at_packet(struct context *context,
+			    struct descriptor *d,
+			    struct descriptor *last)
+{
+	struct driver_data *driver_data;
+	struct fw_packet *packet;
+	struct fw_ohci *ohci = context->ohci;
+	dma_addr_t payload_bus;
+	int evt;
+
+	if (last->transfer_status == 0)
+		/* This descriptor isn't done yet, stop iteration. */
+		return 0;
+
+	driver_data = (struct driver_data *) &d[3];
+	packet = driver_data->packet;
+	if (packet == NULL)
+		/* This packet was cancelled, just continue. */
+		return 1;
+
+	payload_bus = le32_to_cpu(last->data_address);
+	if (payload_bus != 0)
+		dma_unmap_single(ohci->card.device, payload_bus,
+				 packet->payload_length, DMA_TO_DEVICE);
+
+	evt = le16_to_cpu(last->transfer_status) & 0x1f;
+	packet->timestamp = le16_to_cpu(last->res_count);
+
+	switch (evt) {
+	case OHCI1394_evt_timeout:
+		/* Async response transmit timed out. */
+		packet->ack = RCODE_CANCELLED;
+		break;
+
+	case OHCI1394_evt_flushed:
+		/*
+		 * The packet was flushed should give same error as
+		 * when we try to use a stale generation count.
+		 */
+		packet->ack = RCODE_GENERATION;
+		break;
+
+	case OHCI1394_evt_missing_ack:
+		/*
+		 * Using a valid (current) generation count, but the
+		 * node is not on the bus or not sending acks.
+		 */
+		packet->ack = RCODE_NO_ACK;
+		break;
+
+	case ACK_COMPLETE + 0x10:
+	case ACK_PENDING + 0x10:
+	case ACK_BUSY_X + 0x10:
+	case ACK_BUSY_A + 0x10:
+	case ACK_BUSY_B + 0x10:
+	case ACK_DATA_ERROR + 0x10:
+	case ACK_TYPE_ERROR + 0x10:
+		packet->ack = evt - 0x10;
+		break;
+
+	default:
+		packet->ack = RCODE_SEND_ERROR;
+		break;
+	}
+
+	packet->callback(packet, &ohci->card, packet->ack);
+
+	return 1;
+}
+
+#define HEADER_GET_DESTINATION(q)	(((q) >> 16) & 0xffff)
+#define HEADER_GET_TCODE(q)		(((q) >> 4) & 0x0f)
+#define HEADER_GET_OFFSET_HIGH(q)	(((q) >> 0) & 0xffff)
+#define HEADER_GET_DATA_LENGTH(q)	(((q) >> 16) & 0xffff)
+#define HEADER_GET_EXTENDED_TCODE(q)	(((q) >> 0) & 0xffff)
+
+static void
+handle_local_rom(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr)
+{
+	struct fw_packet response;
+	int tcode, length, i;
+
+	tcode = HEADER_GET_TCODE(packet->header[0]);
+	if (TCODE_IS_BLOCK_PACKET(tcode))
+		length = HEADER_GET_DATA_LENGTH(packet->header[3]);
+	else
+		length = 4;
+
+	i = csr - CSR_CONFIG_ROM;
+	if (i + length > CONFIG_ROM_SIZE) {
+		fw_fill_response(&response, packet->header,
+				 RCODE_ADDRESS_ERROR, NULL, 0);
+	} else if (!TCODE_IS_READ_REQUEST(tcode)) {
+		fw_fill_response(&response, packet->header,
+				 RCODE_TYPE_ERROR, NULL, 0);
+	} else {
+		fw_fill_response(&response, packet->header, RCODE_COMPLETE,
+				 (void *) ohci->config_rom + i, length);
+	}
+
+	fw_core_handle_response(&ohci->card, &response);
+}
+
+static void
+handle_local_lock(struct fw_ohci *ohci, struct fw_packet *packet, u32 csr)
+{
+	struct fw_packet response;
+	int tcode, length, ext_tcode, sel;
+	__be32 *payload, lock_old;
+	u32 lock_arg, lock_data;
+
+	tcode = HEADER_GET_TCODE(packet->header[0]);
+	length = HEADER_GET_DATA_LENGTH(packet->header[3]);
+	payload = packet->payload;
+	ext_tcode = HEADER_GET_EXTENDED_TCODE(packet->header[3]);
+
+	if (tcode == TCODE_LOCK_REQUEST &&
+	    ext_tcode == EXTCODE_COMPARE_SWAP && length == 8) {
+		lock_arg = be32_to_cpu(payload[0]);
+		lock_data = be32_to_cpu(payload[1]);
+	} else if (tcode == TCODE_READ_QUADLET_REQUEST) {
+		lock_arg = 0;
+		lock_data = 0;
+	} else {
+		fw_fill_response(&response, packet->header,
+				 RCODE_TYPE_ERROR, NULL, 0);
+		goto out;
+	}
+
+	sel = (csr - CSR_BUS_MANAGER_ID) / 4;
+	reg_write(ohci, OHCI1394_CSRData, lock_data);
+	reg_write(ohci, OHCI1394_CSRCompareData, lock_arg);
+	reg_write(ohci, OHCI1394_CSRControl, sel);
+
+	if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
+		lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData));
+	else
+		fw_notify("swap not done yet\n");
+
+	fw_fill_response(&response, packet->header,
+			 RCODE_COMPLETE, &lock_old, sizeof(lock_old));
+ out:
+	fw_core_handle_response(&ohci->card, &response);
+}
+
+static void
+handle_local_request(struct context *ctx, struct fw_packet *packet)
+{
+	u64 offset;
+	u32 csr;
+
+	if (ctx == &ctx->ohci->at_request_ctx) {
+		packet->ack = ACK_PENDING;
+		packet->callback(packet, &ctx->ohci->card, packet->ack);
+	}
+
+	offset =
+		((unsigned long long)
+		 HEADER_GET_OFFSET_HIGH(packet->header[1]) << 32) |
+		packet->header[2];
+	csr = offset - CSR_REGISTER_BASE;
+
+	/* Handle config rom reads. */
+	if (csr >= CSR_CONFIG_ROM && csr < CSR_CONFIG_ROM_END)
+		handle_local_rom(ctx->ohci, packet, csr);
+	else switch (csr) {
+	case CSR_BUS_MANAGER_ID:
+	case CSR_BANDWIDTH_AVAILABLE:
+	case CSR_CHANNELS_AVAILABLE_HI:
+	case CSR_CHANNELS_AVAILABLE_LO:
+		handle_local_lock(ctx->ohci, packet, csr);
+		break;
+	default:
+		if (ctx == &ctx->ohci->at_request_ctx)
+			fw_core_handle_request(&ctx->ohci->card, packet);
+		else
+			fw_core_handle_response(&ctx->ohci->card, packet);
+		break;
+	}
+
+	if (ctx == &ctx->ohci->at_response_ctx) {
+		packet->ack = ACK_COMPLETE;
+		packet->callback(packet, &ctx->ohci->card, packet->ack);
+	}
+}
+
+static void
+at_context_transmit(struct context *ctx, struct fw_packet *packet)
+{
+	unsigned long flags;
+	int retval;
+
+	spin_lock_irqsave(&ctx->ohci->lock, flags);
+
+	if (HEADER_GET_DESTINATION(packet->header[0]) == ctx->ohci->node_id &&
+	    ctx->ohci->generation == packet->generation) {
+		spin_unlock_irqrestore(&ctx->ohci->lock, flags);
+		handle_local_request(ctx, packet);
+		return;
+	}
+
+	retval = at_context_queue_packet(ctx, packet);
+	spin_unlock_irqrestore(&ctx->ohci->lock, flags);
+
+	if (retval < 0)
+		packet->callback(packet, &ctx->ohci->card, packet->ack);
+	
+}
+
+static void bus_reset_tasklet(unsigned long data)
+{
+	struct fw_ohci *ohci = (struct fw_ohci *)data;
+	int self_id_count, i, j, reg;
+	int generation, new_generation;
+	unsigned long flags;
+
+	reg = reg_read(ohci, OHCI1394_NodeID);
+	if (!(reg & OHCI1394_NodeID_idValid)) {
+		fw_error("node ID not valid, new bus reset in progress\n");
+		return;
+	}
+	ohci->node_id = reg & 0xffff;
+
+	/*
+	 * The count in the SelfIDCount register is the number of
+	 * bytes in the self ID receive buffer.  Since we also receive
+	 * the inverted quadlets and a header quadlet, we shift one
+	 * bit extra to get the actual number of self IDs.
+	 */
+
+	self_id_count = (reg_read(ohci, OHCI1394_SelfIDCount) >> 3) & 0x3ff;
+	generation = (le32_to_cpu(ohci->self_id_cpu[0]) >> 16) & 0xff;
+
+	for (i = 1, j = 0; j < self_id_count; i += 2, j++) {
+		if (ohci->self_id_cpu[i] != ~ohci->self_id_cpu[i + 1])
+			fw_error("inconsistent self IDs\n");
+		ohci->self_id_buffer[j] = le32_to_cpu(ohci->self_id_cpu[i]);
+	}
+
+	/*
+	 * Check the consistency of the self IDs we just read.  The
+	 * problem we face is that a new bus reset can start while we
+	 * read out the self IDs from the DMA buffer. If this happens,
+	 * the DMA buffer will be overwritten with new self IDs and we
+	 * will read out inconsistent data.  The OHCI specification
+	 * (section 11.2) recommends a technique similar to
+	 * linux/seqlock.h, where we remember the generation of the
+	 * self IDs in the buffer before reading them out and compare
+	 * it to the current generation after reading them out.  If
+	 * the two generations match we know we have a consistent set
+	 * of self IDs.
+	 */
+
+	new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff;
+	if (new_generation != generation) {
+		fw_notify("recursive bus reset detected, "
+			  "discarding self ids\n");
+		return;
+	}
+
+	/* FIXME: Document how the locking works. */
+	spin_lock_irqsave(&ohci->lock, flags);
+
+	ohci->generation = generation;
+	context_stop(&ohci->at_request_ctx);
+	context_stop(&ohci->at_response_ctx);
+	reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
+
+	/*
+	 * This next bit is unrelated to the AT context stuff but we
+	 * have to do it under the spinlock also.  If a new config rom
+	 * was set up before this reset, the old one is now no longer
+	 * in use and we can free it. Update the config rom pointers
+	 * to point to the current config rom and clear the
+	 * next_config_rom pointer so a new udpate can take place.
+	 */
+
+	if (ohci->next_config_rom != NULL) {
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  ohci->config_rom, ohci->config_rom_bus);
+		ohci->config_rom      = ohci->next_config_rom;
+		ohci->config_rom_bus  = ohci->next_config_rom_bus;
+		ohci->next_config_rom = NULL;
+
+		/*
+		 * Restore config_rom image and manually update
+		 * config_rom registers.  Writing the header quadlet
+		 * will indicate that the config rom is ready, so we
+		 * do that last.
+		 */
+		reg_write(ohci, OHCI1394_BusOptions,
+			  be32_to_cpu(ohci->config_rom[2]));
+		ohci->config_rom[0] = cpu_to_be32(ohci->next_header);
+		reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header);
+	}
+
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation,
+				 self_id_count, ohci->self_id_buffer);
+}
+
+static irqreturn_t irq_handler(int irq, void *data)
+{
+	struct fw_ohci *ohci = data;
+	u32 event, iso_event, cycle_time;
+	int i;
+
+	event = reg_read(ohci, OHCI1394_IntEventClear);
+
+	if (!event)
+		return IRQ_NONE;
+
+	reg_write(ohci, OHCI1394_IntEventClear, event);
+
+	if (event & OHCI1394_selfIDComplete)
+		tasklet_schedule(&ohci->bus_reset_tasklet);
+
+	if (event & OHCI1394_RQPkt)
+		tasklet_schedule(&ohci->ar_request_ctx.tasklet);
+
+	if (event & OHCI1394_RSPkt)
+		tasklet_schedule(&ohci->ar_response_ctx.tasklet);
+
+	if (event & OHCI1394_reqTxComplete)
+		tasklet_schedule(&ohci->at_request_ctx.tasklet);
+
+	if (event & OHCI1394_respTxComplete)
+		tasklet_schedule(&ohci->at_response_ctx.tasklet);
+
+	iso_event = reg_read(ohci, OHCI1394_IsoRecvIntEventClear);
+	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, iso_event);
+
+	while (iso_event) {
+		i = ffs(iso_event) - 1;
+		tasklet_schedule(&ohci->ir_context_list[i].context.tasklet);
+		iso_event &= ~(1 << i);
+	}
+
+	iso_event = reg_read(ohci, OHCI1394_IsoXmitIntEventClear);
+	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, iso_event);
+
+	while (iso_event) {
+		i = ffs(iso_event) - 1;
+		tasklet_schedule(&ohci->it_context_list[i].context.tasklet);
+		iso_event &= ~(1 << i);
+	}
+
+	if (event & OHCI1394_cycle64Seconds) {
+		cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+		if ((cycle_time & 0x80000000) == 0)
+			ohci->bus_seconds++;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	struct pci_dev *dev = to_pci_dev(card->device);
+
+	/*
+	 * When the link is not yet enabled, the atomic config rom
+	 * update mechanism described below in ohci_set_config_rom()
+	 * is not active.  We have to update ConfigRomHeader and
+	 * BusOptions manually, and the write to ConfigROMmap takes
+	 * effect immediately.  We tie this to the enabling of the
+	 * link, so we have a valid config rom before enabling - the
+	 * OHCI requires that ConfigROMhdr and BusOptions have valid
+	 * values before enabling.
+	 *
+	 * However, when the ConfigROMmap is written, some controllers
+	 * always read back quadlets 0 and 2 from the config rom to
+	 * the ConfigRomHeader and BusOptions registers on bus reset.
+	 * They shouldn't do that in this initial case where the link
+	 * isn't enabled.  This means we have to use the same
+	 * workaround here, setting the bus header to 0 and then write
+	 * the right values in the bus reset tasklet.
+	 */
+
+	ohci->next_config_rom =
+		dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				   &ohci->next_config_rom_bus, GFP_KERNEL);
+	if (ohci->next_config_rom == NULL)
+		return -ENOMEM;
+
+	memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE);
+	fw_memcpy_to_be32(ohci->next_config_rom, config_rom, length * 4);
+
+	ohci->next_header = config_rom[0];
+	ohci->next_config_rom[0] = 0;
+	reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
+	reg_write(ohci, OHCI1394_BusOptions, config_rom[2]);
+	reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
+
+	reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
+
+	if (request_irq(dev->irq, irq_handler,
+			IRQF_SHARED, ohci_driver_name, ohci)) {
+		fw_error("Failed to allocate shared interrupt %d.\n",
+			 dev->irq);
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  ohci->config_rom, ohci->config_rom_bus);
+		return -EIO;
+	}
+
+	reg_write(ohci, OHCI1394_HCControlSet,
+		  OHCI1394_HCControl_linkEnable |
+		  OHCI1394_HCControl_BIBimageValid);
+	flush_writes(ohci);
+
+	/*
+	 * We are ready to go, initiate bus reset to finish the
+	 * initialization.
+	 */
+
+	fw_core_initiate_bus_reset(&ohci->card, 1);
+
+	return 0;
+}
+
+static int
+ohci_set_config_rom(struct fw_card *card, u32 *config_rom, size_t length)
+{
+	struct fw_ohci *ohci;
+	unsigned long flags;
+	int retval = 0;
+	__be32 *next_config_rom;
+	dma_addr_t next_config_rom_bus;
+
+	ohci = fw_ohci(card);
+
+	/*
+	 * When the OHCI controller is enabled, the config rom update
+	 * mechanism is a bit tricky, but easy enough to use.  See
+	 * section 5.5.6 in the OHCI specification.
+	 *
+	 * The OHCI controller caches the new config rom address in a
+	 * shadow register (ConfigROMmapNext) and needs a bus reset
+	 * for the changes to take place.  When the bus reset is
+	 * detected, the controller loads the new values for the
+	 * ConfigRomHeader and BusOptions registers from the specified
+	 * config rom and loads ConfigROMmap from the ConfigROMmapNext
+	 * shadow register. All automatically and atomically.
+	 *
+	 * Now, there's a twist to this story.  The automatic load of
+	 * ConfigRomHeader and BusOptions doesn't honor the
+	 * noByteSwapData bit, so with a be32 config rom, the
+	 * controller will load be32 values in to these registers
+	 * during the atomic update, even on litte endian
+	 * architectures.  The workaround we use is to put a 0 in the
+	 * header quadlet; 0 is endian agnostic and means that the
+	 * config rom isn't ready yet.  In the bus reset tasklet we
+	 * then set up the real values for the two registers.
+	 *
+	 * We use ohci->lock to avoid racing with the code that sets
+	 * ohci->next_config_rom to NULL (see bus_reset_tasklet).
+	 */
+
+	next_config_rom =
+		dma_alloc_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				   &next_config_rom_bus, GFP_KERNEL);
+	if (next_config_rom == NULL)
+		return -ENOMEM;
+
+	spin_lock_irqsave(&ohci->lock, flags);
+
+	if (ohci->next_config_rom == NULL) {
+		ohci->next_config_rom = next_config_rom;
+		ohci->next_config_rom_bus = next_config_rom_bus;
+
+		memset(ohci->next_config_rom, 0, CONFIG_ROM_SIZE);
+		fw_memcpy_to_be32(ohci->next_config_rom, config_rom,
+				  length * 4);
+
+		ohci->next_header = config_rom[0];
+		ohci->next_config_rom[0] = 0;
+
+		reg_write(ohci, OHCI1394_ConfigROMmap,
+			  ohci->next_config_rom_bus);
+	} else {
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  next_config_rom, next_config_rom_bus);
+		retval = -EBUSY;
+	}
+
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	/*
+	 * Now initiate a bus reset to have the changes take
+	 * effect. We clean up the old config rom memory and DMA
+	 * mappings in the bus reset tasklet, since the OHCI
+	 * controller could need to access it before the bus reset
+	 * takes effect.
+	 */
+	if (retval == 0)
+		fw_core_initiate_bus_reset(&ohci->card, 1);
+
+	return retval;
+}
+
+static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+
+	at_context_transmit(&ohci->at_request_ctx, packet);
+}
+
+static void ohci_send_response(struct fw_card *card, struct fw_packet *packet)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+
+	at_context_transmit(&ohci->at_response_ctx, packet);
+}
+
+static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	struct context *ctx = &ohci->at_request_ctx;
+	struct driver_data *driver_data = packet->driver_data;
+	int retval = -ENOENT;
+
+	tasklet_disable(&ctx->tasklet);
+
+	if (packet->ack != 0)
+		goto out;
+
+	driver_data->packet = NULL;
+	packet->ack = RCODE_CANCELLED;
+	packet->callback(packet, &ohci->card, packet->ack);
+	retval = 0;
+
+ out:
+	tasklet_enable(&ctx->tasklet);
+
+	return retval;
+}
+
+static int
+ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	unsigned long flags;
+	int n, retval = 0;
+
+	/*
+	 * FIXME:  Make sure this bitmask is cleared when we clear the busReset
+	 * interrupt bit.  Clear physReqResourceAllBuses on bus reset.
+	 */
+
+	spin_lock_irqsave(&ohci->lock, flags);
+
+	if (ohci->generation != generation) {
+		retval = -ESTALE;
+		goto out;
+	}
+
+	/*
+	 * Note, if the node ID contains a non-local bus ID, physical DMA is
+	 * enabled for _all_ nodes on remote buses.
+	 */
+
+	n = (node_id & 0xffc0) == LOCAL_BUS ? node_id & 0x3f : 63;
+	if (n < 32)
+		reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 1 << n);
+	else
+		reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32));
+
+	flush_writes(ohci);
+ out:
+	spin_unlock_irqrestore(&ohci->lock, flags);
+	return retval;
+}
+
+static u64
+ohci_get_bus_time(struct fw_card *card)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	u32 cycle_time;
+	u64 bus_time;
+
+	cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+	bus_time = ((u64) ohci->bus_seconds << 32) | cycle_time;
+
+	return bus_time;
+}
+
+static int handle_ir_dualbuffer_packet(struct context *context,
+				       struct descriptor *d,
+				       struct descriptor *last)
+{
+	struct iso_context *ctx =
+		container_of(context, struct iso_context, context);
+	struct db_descriptor *db = (struct db_descriptor *) d;
+	__le32 *ir_header;
+	size_t header_length;
+	void *p, *end;
+	int i;
+
+	if (db->first_res_count > 0 && db->second_res_count > 0)
+		/* This descriptor isn't done yet, stop iteration. */
+		return 0;
+
+	header_length = le16_to_cpu(db->first_req_count) -
+		le16_to_cpu(db->first_res_count);
+
+	i = ctx->header_length;
+	p = db + 1;
+	end = p + header_length;
+	while (p < end && i + ctx->base.header_size <= PAGE_SIZE) {
+		/*
+		 * The iso header is byteswapped to little endian by
+		 * the controller, but the remaining header quadlets
+		 * are big endian.  We want to present all the headers
+		 * as big endian, so we have to swap the first
+		 * quadlet.
+		 */
+		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
+		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
+		i += ctx->base.header_size;
+		p += ctx->base.header_size + 4;
+	}
+
+	ctx->header_length = i;
+
+	if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) {
+		ir_header = (__le32 *) (db + 1);
+		ctx->base.callback(&ctx->base,
+				   le32_to_cpu(ir_header[0]) & 0xffff,
+				   ctx->header_length, ctx->header,
+				   ctx->base.callback_data);
+		ctx->header_length = 0;
+	}
+
+	return 1;
+}
+
+static int handle_it_packet(struct context *context,
+			    struct descriptor *d,
+			    struct descriptor *last)
+{
+	struct iso_context *ctx =
+		container_of(context, struct iso_context, context);
+
+	if (last->transfer_status == 0)
+		/* This descriptor isn't done yet, stop iteration. */
+		return 0;
+
+	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
+		ctx->base.callback(&ctx->base, le16_to_cpu(last->res_count),
+				   0, NULL, ctx->base.callback_data);
+
+	return 1;
+}
+
+static struct fw_iso_context *
+ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
+{
+	struct fw_ohci *ohci = fw_ohci(card);
+	struct iso_context *ctx, *list;
+	descriptor_callback_t callback;
+	u32 *mask, regs;
+	unsigned long flags;
+	int index, retval = -ENOMEM;
+
+	if (type == FW_ISO_CONTEXT_TRANSMIT) {
+		mask = &ohci->it_context_mask;
+		list = ohci->it_context_list;
+		callback = handle_it_packet;
+	} else {
+		mask = &ohci->ir_context_mask;
+		list = ohci->ir_context_list;
+		callback = handle_ir_dualbuffer_packet;
+	}
+
+	/* FIXME: We need a fallback for pre 1.1 OHCI. */
+	if (callback == handle_ir_dualbuffer_packet &&
+	    ohci->version < OHCI_VERSION_1_1)
+		return ERR_PTR(-EINVAL);
+
+	spin_lock_irqsave(&ohci->lock, flags);
+	index = ffs(*mask) - 1;
+	if (index >= 0)
+		*mask &= ~(1 << index);
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	if (index < 0)
+		return ERR_PTR(-EBUSY);
+
+	if (type == FW_ISO_CONTEXT_TRANSMIT)
+		regs = OHCI1394_IsoXmitContextBase(index);
+	else
+		regs = OHCI1394_IsoRcvContextBase(index);
+
+	ctx = &list[index];
+	memset(ctx, 0, sizeof(*ctx));
+	ctx->header_length = 0;
+	ctx->header = (void *) __get_free_page(GFP_KERNEL);
+	if (ctx->header == NULL)
+		goto out;
+
+	retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE,
+			      regs, callback);
+	if (retval < 0)
+		goto out_with_header;
+
+	return &ctx->base;
+
+ out_with_header:
+	free_page((unsigned long)ctx->header);
+ out:
+	spin_lock_irqsave(&ohci->lock, flags);
+	*mask |= 1 << index;
+	spin_unlock_irqrestore(&ohci->lock, flags);
+
+	return ERR_PTR(retval);
+}
+
+static int ohci_start_iso(struct fw_iso_context *base,
+			  s32 cycle, u32 sync, u32 tags)
+{
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+	struct fw_ohci *ohci = ctx->context.ohci;
+	u32 control, match;
+	int index;
+
+	if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
+		index = ctx - ohci->it_context_list;
+		match = 0;
+		if (cycle >= 0)
+			match = IT_CONTEXT_CYCLE_MATCH_ENABLE |
+				(cycle & 0x7fff) << 16;
+
+		reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 1 << index);
+		reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << index);
+		context_run(&ctx->context, match);
+	} else {
+		index = ctx - ohci->ir_context_list;
+		control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER;
+		match = (tags << 28) | (sync << 8) | ctx->base.channel;
+		if (cycle >= 0) {
+			match |= (cycle & 0x07fff) << 12;
+			control |= IR_CONTEXT_CYCLE_MATCH_ENABLE;
+		}
+
+		reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index);
+		reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index);
+		reg_write(ohci, CONTEXT_MATCH(ctx->context.regs), match);
+		context_run(&ctx->context, control);
+	}
+
+	return 0;
+}
+
+static int ohci_stop_iso(struct fw_iso_context *base)
+{
+	struct fw_ohci *ohci = fw_ohci(base->card);
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+	int index;
+
+	if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
+		index = ctx - ohci->it_context_list;
+		reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 1 << index);
+	} else {
+		index = ctx - ohci->ir_context_list;
+		reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 1 << index);
+	}
+	flush_writes(ohci);
+	context_stop(&ctx->context);
+
+	return 0;
+}
+
+static void ohci_free_iso_context(struct fw_iso_context *base)
+{
+	struct fw_ohci *ohci = fw_ohci(base->card);
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+	unsigned long flags;
+	int index;
+
+	ohci_stop_iso(base);
+	context_release(&ctx->context);
+	free_page((unsigned long)ctx->header);
+
+	spin_lock_irqsave(&ohci->lock, flags);
+
+	if (ctx->base.type == FW_ISO_CONTEXT_TRANSMIT) {
+		index = ctx - ohci->it_context_list;
+		ohci->it_context_mask |= 1 << index;
+	} else {
+		index = ctx - ohci->ir_context_list;
+		ohci->ir_context_mask |= 1 << index;
+	}
+
+	spin_unlock_irqrestore(&ohci->lock, flags);
+}
+
+static int
+ohci_queue_iso_transmit(struct fw_iso_context *base,
+			struct fw_iso_packet *packet,
+			struct fw_iso_buffer *buffer,
+			unsigned long payload)
+{
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+	struct descriptor *d, *last, *pd;
+	struct fw_iso_packet *p;
+	__le32 *header;
+	dma_addr_t d_bus, page_bus;
+	u32 z, header_z, payload_z, irq;
+	u32 payload_index, payload_end_index, next_page_index;
+	int page, end_page, i, length, offset;
+
+	/*
+	 * FIXME: Cycle lost behavior should be configurable: lose
+	 * packet, retransmit or terminate..
+	 */
+
+	p = packet;
+	payload_index = payload;
+
+	if (p->skip)
+		z = 1;
+	else
+		z = 2;
+	if (p->header_length > 0)
+		z++;
+
+	/* Determine the first page the payload isn't contained in. */
+	end_page = PAGE_ALIGN(payload_index + p->payload_length) >> PAGE_SHIFT;
+	if (p->payload_length > 0)
+		payload_z = end_page - (payload_index >> PAGE_SHIFT);
+	else
+		payload_z = 0;
+
+	z += payload_z;
+
+	/* Get header size in number of descriptors. */
+	header_z = DIV_ROUND_UP(p->header_length, sizeof(*d));
+
+	d = context_get_descriptors(&ctx->context, z + header_z, &d_bus);
+	if (d == NULL)
+		return -ENOMEM;
+
+	if (!p->skip) {
+		d[0].control   = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE);
+		d[0].req_count = cpu_to_le16(8);
+
+		header = (__le32 *) &d[1];
+		header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) |
+					IT_HEADER_TAG(p->tag) |
+					IT_HEADER_TCODE(TCODE_STREAM_DATA) |
+					IT_HEADER_CHANNEL(ctx->base.channel) |
+					IT_HEADER_SPEED(ctx->base.speed));
+		header[1] =
+			cpu_to_le32(IT_HEADER_DATA_LENGTH(p->header_length +
+							  p->payload_length));
+	}
+
+	if (p->header_length > 0) {
+		d[2].req_count    = cpu_to_le16(p->header_length);
+		d[2].data_address = cpu_to_le32(d_bus + z * sizeof(*d));
+		memcpy(&d[z], p->header, p->header_length);
+	}
+
+	pd = d + z - payload_z;
+	payload_end_index = payload_index + p->payload_length;
+	for (i = 0; i < payload_z; i++) {
+		page               = payload_index >> PAGE_SHIFT;
+		offset             = payload_index & ~PAGE_MASK;
+		next_page_index    = (page + 1) << PAGE_SHIFT;
+		length             =
+			min(next_page_index, payload_end_index) - payload_index;
+		pd[i].req_count    = cpu_to_le16(length);
+
+		page_bus = page_private(buffer->pages[page]);
+		pd[i].data_address = cpu_to_le32(page_bus + offset);
+
+		payload_index += length;
+	}
+
+	if (p->interrupt)
+		irq = DESCRIPTOR_IRQ_ALWAYS;
+	else
+		irq = DESCRIPTOR_NO_IRQ;
+
+	last = z == 2 ? d : d + z - 1;
+	last->control |= cpu_to_le16(DESCRIPTOR_OUTPUT_LAST |
+				     DESCRIPTOR_STATUS |
+				     DESCRIPTOR_BRANCH_ALWAYS |
+				     irq);
+
+	context_append(&ctx->context, d, z, header_z);
+
+	return 0;
+}
+
+static int
+ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
+				  struct fw_iso_packet *packet,
+				  struct fw_iso_buffer *buffer,
+				  unsigned long payload)
+{
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+	struct db_descriptor *db = NULL;
+	struct descriptor *d;
+	struct fw_iso_packet *p;
+	dma_addr_t d_bus, page_bus;
+	u32 z, header_z, length, rest;
+	int page, offset, packet_count, header_size;
+
+	/*
+	 * FIXME: Cycle lost behavior should be configurable: lose
+	 * packet, retransmit or terminate..
+	 */
+
+	if (packet->skip) {
+		d = context_get_descriptors(&ctx->context, 2, &d_bus);
+		if (d == NULL)
+			return -ENOMEM;
+
+		db = (struct db_descriptor *) d;
+		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
+					  DESCRIPTOR_BRANCH_ALWAYS |
+					  DESCRIPTOR_WAIT);
+		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
+		context_append(&ctx->context, d, 2, 0);
+	}
+
+	p = packet;
+	z = 2;
+
+	/*
+	 * The OHCI controller puts the status word in the header
+	 * buffer too, so we need 4 extra bytes per packet.
+	 */
+	packet_count = p->header_length / ctx->base.header_size;
+	header_size = packet_count * (ctx->base.header_size + 4);
+
+	/* Get header size in number of descriptors. */
+	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
+	page     = payload >> PAGE_SHIFT;
+	offset   = payload & ~PAGE_MASK;
+	rest     = p->payload_length;
+
+	/* FIXME: OHCI 1.0 doesn't support dual buffer receive */
+	/* FIXME: make packet-per-buffer/dual-buffer a context option */
+	while (rest > 0) {
+		d = context_get_descriptors(&ctx->context,
+					    z + header_z, &d_bus);
+		if (d == NULL)
+			return -ENOMEM;
+
+		db = (struct db_descriptor *) d;
+		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
+					  DESCRIPTOR_BRANCH_ALWAYS);
+		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
+		db->first_req_count = cpu_to_le16(header_size);
+		db->first_res_count = db->first_req_count;
+		db->first_buffer = cpu_to_le32(d_bus + sizeof(*db));
+
+		if (offset + rest < PAGE_SIZE)
+			length = rest;
+		else
+			length = PAGE_SIZE - offset;
+
+		db->second_req_count = cpu_to_le16(length);
+		db->second_res_count = db->second_req_count;
+		page_bus = page_private(buffer->pages[page]);
+		db->second_buffer = cpu_to_le32(page_bus + offset);
+
+		if (p->interrupt && length == rest)
+			db->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
+
+		context_append(&ctx->context, d, z, header_z);
+		offset = (offset + length) & ~PAGE_MASK;
+		rest -= length;
+		page++;
+	}
+
+	return 0;
+}
+
+static int
+ohci_queue_iso(struct fw_iso_context *base,
+	       struct fw_iso_packet *packet,
+	       struct fw_iso_buffer *buffer,
+	       unsigned long payload)
+{
+	struct iso_context *ctx = container_of(base, struct iso_context, base);
+
+	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
+		return ohci_queue_iso_transmit(base, packet, buffer, payload);
+	else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
+		return ohci_queue_iso_receive_dualbuffer(base, packet,
+							 buffer, payload);
+	else
+		/* FIXME: Implement fallback for OHCI 1.0 controllers. */
+		return -EINVAL;
+}
+
+static const struct fw_card_driver ohci_driver = {
+	.name			= ohci_driver_name,
+	.enable			= ohci_enable,
+	.update_phy_reg		= ohci_update_phy_reg,
+	.set_config_rom		= ohci_set_config_rom,
+	.send_request		= ohci_send_request,
+	.send_response		= ohci_send_response,
+	.cancel_packet		= ohci_cancel_packet,
+	.enable_phys_dma	= ohci_enable_phys_dma,
+	.get_bus_time		= ohci_get_bus_time,
+
+	.allocate_iso_context	= ohci_allocate_iso_context,
+	.free_iso_context	= ohci_free_iso_context,
+	.queue_iso		= ohci_queue_iso,
+	.start_iso		= ohci_start_iso,
+	.stop_iso		= ohci_stop_iso,
+};
+
+static int software_reset(struct fw_ohci *ohci)
+{
+	int i;
+
+	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+
+	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
+		if ((reg_read(ohci, OHCI1394_HCControlSet) &
+		     OHCI1394_HCControl_softReset) == 0)
+			return 0;
+		msleep(1);
+	}
+
+	return -EBUSY;
+}
+
+static int __devinit
+pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+	struct fw_ohci *ohci;
+	u32 bus_options, max_receive, link_speed;
+	u64 guid;
+	int err;
+	size_t size;
+
+	ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
+	if (ohci == NULL) {
+		fw_error("Could not malloc fw_ohci data.\n");
+		return -ENOMEM;
+	}
+
+	fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev);
+
+	err = pci_enable_device(dev);
+	if (err) {
+		fw_error("Failed to enable OHCI hardware.\n");
+		goto fail_put_card;
+	}
+
+	pci_set_master(dev);
+	pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
+	pci_set_drvdata(dev, ohci);
+
+	spin_lock_init(&ohci->lock);
+
+	tasklet_init(&ohci->bus_reset_tasklet,
+		     bus_reset_tasklet, (unsigned long)ohci);
+
+	err = pci_request_region(dev, 0, ohci_driver_name);
+	if (err) {
+		fw_error("MMIO resource unavailable\n");
+		goto fail_disable;
+	}
+
+	ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE);
+	if (ohci->registers == NULL) {
+		fw_error("Failed to remap registers\n");
+		err = -ENXIO;
+		goto fail_iomem;
+	}
+
+	if (software_reset(ohci)) {
+		fw_error("Failed to reset ohci card.\n");
+		err = -EBUSY;
+		goto fail_registers;
+	}
+
+	/*
+	 * Now enable LPS, which we need in order to start accessing
+	 * most of the registers.  In fact, on some cards (ALI M5251),
+	 * accessing registers in the SClk domain without LPS enabled
+	 * will lock up the machine.  Wait 50msec to make sure we have
+	 * full link enabled.
+	 */
+	reg_write(ohci, OHCI1394_HCControlSet,
+		  OHCI1394_HCControl_LPS |
+		  OHCI1394_HCControl_postedWriteEnable);
+	flush_writes(ohci);
+	msleep(50);
+
+	reg_write(ohci, OHCI1394_HCControlClear,
+		  OHCI1394_HCControl_noByteSwapData);
+
+	reg_write(ohci, OHCI1394_LinkControlSet,
+		  OHCI1394_LinkControl_rcvSelfID |
+		  OHCI1394_LinkControl_cycleTimerEnable |
+		  OHCI1394_LinkControl_cycleMaster);
+
+	ar_context_init(&ohci->ar_request_ctx, ohci,
+			OHCI1394_AsReqRcvContextControlSet);
+
+	ar_context_init(&ohci->ar_response_ctx, ohci,
+			OHCI1394_AsRspRcvContextControlSet);
+
+	context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE,
+		     OHCI1394_AsReqTrContextControlSet, handle_at_packet);
+
+	context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
+		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
+
+	reg_write(ohci, OHCI1394_ATRetries,
+		  OHCI1394_MAX_AT_REQ_RETRIES |
+		  (OHCI1394_MAX_AT_RESP_RETRIES << 4) |
+		  (OHCI1394_MAX_PHYS_RESP_RETRIES << 8));
+
+	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
+	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
+	size = sizeof(struct iso_context) * hweight32(ohci->it_context_mask);
+	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
+
+	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
+	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
+	size = sizeof(struct iso_context) * hweight32(ohci->ir_context_mask);
+	ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
+
+	if (ohci->it_context_list == NULL || ohci->ir_context_list == NULL) {
+		fw_error("Out of memory for it/ir contexts.\n");
+		err = -ENOMEM;
+		goto fail_registers;
+	}
+
+	/* self-id dma buffer allocation */
+	ohci->self_id_cpu = dma_alloc_coherent(ohci->card.device,
+					       SELF_ID_BUF_SIZE,
+					       &ohci->self_id_bus,
+					       GFP_KERNEL);
+	if (ohci->self_id_cpu == NULL) {
+		fw_error("Out of memory for self ID buffer.\n");
+		err = -ENOMEM;
+		goto fail_registers;
+	}
+
+	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->self_id_bus);
+	reg_write(ohci, OHCI1394_PhyUpperBound, 0x00010000);
+	reg_write(ohci, OHCI1394_IntEventClear, ~0);
+	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
+	reg_write(ohci, OHCI1394_IntMaskSet,
+		  OHCI1394_selfIDComplete |
+		  OHCI1394_RQPkt | OHCI1394_RSPkt |
+		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+		  OHCI1394_isochRx | OHCI1394_isochTx |
+		  OHCI1394_masterIntEnable |
+		  OHCI1394_cycle64Seconds);
+
+	bus_options = reg_read(ohci, OHCI1394_BusOptions);
+	max_receive = (bus_options >> 12) & 0xf;
+	link_speed = bus_options & 0x7;
+	guid = ((u64) reg_read(ohci, OHCI1394_GUIDHi) << 32) |
+		reg_read(ohci, OHCI1394_GUIDLo);
+
+	err = fw_card_add(&ohci->card, max_receive, link_speed, guid);
+	if (err < 0)
+		goto fail_self_id;
+
+	ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff;
+	fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n",
+		  dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff);
+
+	return 0;
+
+ fail_self_id:
+	dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
+			  ohci->self_id_cpu, ohci->self_id_bus);
+ fail_registers:
+	kfree(ohci->it_context_list);
+	kfree(ohci->ir_context_list);
+	pci_iounmap(dev, ohci->registers);
+ fail_iomem:
+	pci_release_region(dev, 0);
+ fail_disable:
+	pci_disable_device(dev);
+ fail_put_card:
+	fw_card_put(&ohci->card);
+
+	return err;
+}
+
+static void pci_remove(struct pci_dev *dev)
+{
+	struct fw_ohci *ohci;
+
+	ohci = pci_get_drvdata(dev);
+	reg_write(ohci, OHCI1394_IntMaskClear, ~0);
+	flush_writes(ohci);
+	fw_core_remove_card(&ohci->card);
+
+	/*
+	 * FIXME: Fail all pending packets here, now that the upper
+	 * layers can't queue any more.
+	 */
+
+	software_reset(ohci);
+	free_irq(dev->irq, ohci);
+	dma_free_coherent(ohci->card.device, SELF_ID_BUF_SIZE,
+			  ohci->self_id_cpu, ohci->self_id_bus);
+	kfree(ohci->it_context_list);
+	kfree(ohci->ir_context_list);
+	pci_iounmap(dev, ohci->registers);
+	pci_release_region(dev, 0);
+	pci_disable_device(dev);
+	fw_card_put(&ohci->card);
+
+	fw_notify("Removed fw-ohci device.\n");
+}
+
+static struct pci_device_id pci_table[] = {
+	{ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_FIREWIRE_OHCI, ~0) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(pci, pci_table);
+
+static struct pci_driver fw_ohci_pci_driver = {
+	.name		= ohci_driver_name,
+	.id_table	= pci_table,
+	.probe		= pci_probe,
+	.remove		= pci_remove,
+};
+
+MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
+MODULE_DESCRIPTION("Driver for PCI OHCI IEEE1394 controllers");
+MODULE_LICENSE("GPL");
+
+/* Provide a module alias so root-on-sbp2 initrds don't break. */
+#ifndef CONFIG_IEEE1394_OHCI1394_MODULE
+MODULE_ALIAS("ohci1394");
+#endif
+
+static int __init fw_ohci_init(void)
+{
+	return pci_register_driver(&fw_ohci_pci_driver);
+}
+
+static void __exit fw_ohci_cleanup(void)
+{
+	pci_unregister_driver(&fw_ohci_pci_driver);
+}
+
+module_init(fw_ohci_init);
+module_exit(fw_ohci_cleanup);
diff --git a/drivers/firewire/fw-ohci.h b/drivers/firewire/fw-ohci.h
new file mode 100644
index 0000000..fa15706
--- /dev/null
+++ b/drivers/firewire/fw-ohci.h
@@ -0,0 +1,153 @@
+#ifndef __fw_ohci_h
+#define __fw_ohci_h
+
+/* OHCI register map */
+
+#define OHCI1394_Version                      0x000
+#define OHCI1394_GUID_ROM                     0x004
+#define OHCI1394_ATRetries                    0x008
+#define OHCI1394_CSRData                      0x00C
+#define OHCI1394_CSRCompareData               0x010
+#define OHCI1394_CSRControl                   0x014
+#define OHCI1394_ConfigROMhdr                 0x018
+#define OHCI1394_BusID                        0x01C
+#define OHCI1394_BusOptions                   0x020
+#define OHCI1394_GUIDHi                       0x024
+#define OHCI1394_GUIDLo                       0x028
+#define OHCI1394_ConfigROMmap                 0x034
+#define OHCI1394_PostedWriteAddressLo         0x038
+#define OHCI1394_PostedWriteAddressHi         0x03C
+#define OHCI1394_VendorID                     0x040
+#define OHCI1394_HCControlSet                 0x050
+#define OHCI1394_HCControlClear               0x054
+#define  OHCI1394_HCControl_BIBimageValid	0x80000000
+#define  OHCI1394_HCControl_noByteSwapData	0x40000000
+#define  OHCI1394_HCControl_programPhyEnable	0x00800000
+#define  OHCI1394_HCControl_aPhyEnhanceEnable	0x00400000
+#define  OHCI1394_HCControl_LPS			0x00080000
+#define  OHCI1394_HCControl_postedWriteEnable	0x00040000
+#define  OHCI1394_HCControl_linkEnable		0x00020000
+#define  OHCI1394_HCControl_softReset		0x00010000
+#define OHCI1394_SelfIDBuffer                 0x064
+#define OHCI1394_SelfIDCount                  0x068
+#define OHCI1394_IRMultiChanMaskHiSet         0x070
+#define OHCI1394_IRMultiChanMaskHiClear       0x074
+#define OHCI1394_IRMultiChanMaskLoSet         0x078
+#define OHCI1394_IRMultiChanMaskLoClear       0x07C
+#define OHCI1394_IntEventSet                  0x080
+#define OHCI1394_IntEventClear                0x084
+#define OHCI1394_IntMaskSet                   0x088
+#define OHCI1394_IntMaskClear                 0x08C
+#define OHCI1394_IsoXmitIntEventSet           0x090
+#define OHCI1394_IsoXmitIntEventClear         0x094
+#define OHCI1394_IsoXmitIntMaskSet            0x098
+#define OHCI1394_IsoXmitIntMaskClear          0x09C
+#define OHCI1394_IsoRecvIntEventSet           0x0A0
+#define OHCI1394_IsoRecvIntEventClear         0x0A4
+#define OHCI1394_IsoRecvIntMaskSet            0x0A8
+#define OHCI1394_IsoRecvIntMaskClear          0x0AC
+#define OHCI1394_InitialBandwidthAvailable    0x0B0
+#define OHCI1394_InitialChannelsAvailableHi   0x0B4
+#define OHCI1394_InitialChannelsAvailableLo   0x0B8
+#define OHCI1394_FairnessControl              0x0DC
+#define OHCI1394_LinkControlSet               0x0E0
+#define OHCI1394_LinkControlClear             0x0E4
+#define   OHCI1394_LinkControl_rcvSelfID	(1 << 9)
+#define   OHCI1394_LinkControl_rcvPhyPkt	(1 << 10)
+#define   OHCI1394_LinkControl_cycleTimerEnable	(1 << 20)
+#define   OHCI1394_LinkControl_cycleMaster	(1 << 21)
+#define   OHCI1394_LinkControl_cycleSource	(1 << 22)
+#define OHCI1394_NodeID                       0x0E8
+#define   OHCI1394_NodeID_idValid             0x80000000
+#define OHCI1394_PhyControl                   0x0EC
+#define   OHCI1394_PhyControl_Read(addr)	(((addr) << 8) | 0x00008000)
+#define   OHCI1394_PhyControl_ReadDone		0x80000000
+#define   OHCI1394_PhyControl_ReadData(r)	(((r) & 0x00ff0000) >> 16)
+#define   OHCI1394_PhyControl_Write(addr, data)	(((addr) << 8) | (data) | 0x00004000)
+#define   OHCI1394_PhyControl_WriteDone		0x00004000
+#define OHCI1394_IsochronousCycleTimer        0x0F0
+#define OHCI1394_AsReqFilterHiSet             0x100
+#define OHCI1394_AsReqFilterHiClear           0x104
+#define OHCI1394_AsReqFilterLoSet             0x108
+#define OHCI1394_AsReqFilterLoClear           0x10C
+#define OHCI1394_PhyReqFilterHiSet            0x110
+#define OHCI1394_PhyReqFilterHiClear          0x114
+#define OHCI1394_PhyReqFilterLoSet            0x118
+#define OHCI1394_PhyReqFilterLoClear          0x11C
+#define OHCI1394_PhyUpperBound                0x120
+
+#define OHCI1394_AsReqTrContextBase           0x180
+#define OHCI1394_AsReqTrContextControlSet     0x180
+#define OHCI1394_AsReqTrContextControlClear   0x184
+#define OHCI1394_AsReqTrCommandPtr            0x18C
+
+#define OHCI1394_AsRspTrContextBase           0x1A0
+#define OHCI1394_AsRspTrContextControlSet     0x1A0
+#define OHCI1394_AsRspTrContextControlClear   0x1A4
+#define OHCI1394_AsRspTrCommandPtr            0x1AC
+
+#define OHCI1394_AsReqRcvContextBase          0x1C0
+#define OHCI1394_AsReqRcvContextControlSet    0x1C0
+#define OHCI1394_AsReqRcvContextControlClear  0x1C4
+#define OHCI1394_AsReqRcvCommandPtr           0x1CC
+
+#define OHCI1394_AsRspRcvContextBase          0x1E0
+#define OHCI1394_AsRspRcvContextControlSet    0x1E0
+#define OHCI1394_AsRspRcvContextControlClear  0x1E4
+#define OHCI1394_AsRspRcvCommandPtr           0x1EC
+
+/* Isochronous transmit registers */
+#define OHCI1394_IsoXmitContextBase(n)           (0x200 + 16 * (n))
+#define OHCI1394_IsoXmitContextControlSet(n)     (0x200 + 16 * (n))
+#define OHCI1394_IsoXmitContextControlClear(n)   (0x204 + 16 * (n))
+#define OHCI1394_IsoXmitCommandPtr(n)            (0x20C + 16 * (n))
+
+/* Isochronous receive registers */
+#define OHCI1394_IsoRcvContextBase(n)         (0x400 + 32 * (n))
+#define OHCI1394_IsoRcvContextControlSet(n)   (0x400 + 32 * (n))
+#define OHCI1394_IsoRcvContextControlClear(n) (0x404 + 32 * (n))
+#define OHCI1394_IsoRcvCommandPtr(n)          (0x40C + 32 * (n))
+#define OHCI1394_IsoRcvContextMatch(n)        (0x410 + 32 * (n))
+
+/* Interrupts Mask/Events */
+#define OHCI1394_reqTxComplete		0x00000001
+#define OHCI1394_respTxComplete		0x00000002
+#define OHCI1394_ARRQ			0x00000004
+#define OHCI1394_ARRS			0x00000008
+#define OHCI1394_RQPkt			0x00000010
+#define OHCI1394_RSPkt			0x00000020
+#define OHCI1394_isochTx		0x00000040
+#define OHCI1394_isochRx		0x00000080
+#define OHCI1394_postedWriteErr		0x00000100
+#define OHCI1394_lockRespErr		0x00000200
+#define OHCI1394_selfIDComplete		0x00010000
+#define OHCI1394_busReset		0x00020000
+#define OHCI1394_phy			0x00080000
+#define OHCI1394_cycleSynch		0x00100000
+#define OHCI1394_cycle64Seconds		0x00200000
+#define OHCI1394_cycleLost		0x00400000
+#define OHCI1394_cycleInconsistent	0x00800000
+#define OHCI1394_unrecoverableError	0x01000000
+#define OHCI1394_cycleTooLong		0x02000000
+#define OHCI1394_phyRegRcvd		0x04000000
+#define OHCI1394_masterIntEnable	0x80000000
+
+#define OHCI1394_evt_no_status		0x0
+#define OHCI1394_evt_long_packet	0x2
+#define OHCI1394_evt_missing_ack	0x3
+#define OHCI1394_evt_underrun		0x4
+#define OHCI1394_evt_overrun		0x5
+#define OHCI1394_evt_descriptor_read	0x6
+#define OHCI1394_evt_data_read		0x7
+#define OHCI1394_evt_data_write		0x8
+#define OHCI1394_evt_bus_reset		0x9
+#define OHCI1394_evt_timeout		0xa
+#define OHCI1394_evt_tcode_err		0xb
+#define OHCI1394_evt_reserved_b		0xc
+#define OHCI1394_evt_reserved_c		0xd
+#define OHCI1394_evt_unknown		0xe
+#define OHCI1394_evt_flushed		0xf
+
+#define OHCI1394_phy_tcode		0xe
+
+#endif /* __fw_ohci_h */
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
new file mode 100644
index 0000000..6830041
--- /dev/null
+++ b/drivers/firewire/fw-sbp2.c
@@ -0,0 +1,1147 @@
+/*
+ * SBP2 driver (SCSI over IEEE1394)
+ *
+ * Copyright (C) 2005-2007  Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * The basic structure of this driver is based on the old storage driver,
+ * drivers/ieee1394/sbp2.c, originally written by
+ *     James Goodwin <jamesg@filanet.com>
+ * with later contributions and ongoing maintenance from
+ *     Ben Collins <bcollins@debian.org>,
+ *     Stefan Richter <stefanr@s5r6.in-berlin.de>
+ * and many others.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/device.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/timer.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include "fw-transaction.h"
+#include "fw-topology.h"
+#include "fw-device.h"
+
+/* I don't know why the SCSI stack doesn't define something like this... */
+typedef void (*scsi_done_fn_t)(struct scsi_cmnd *);
+
+static const char sbp2_driver_name[] = "sbp2";
+
+struct sbp2_device {
+	struct kref kref;
+	struct fw_unit *unit;
+	struct fw_address_handler address_handler;
+	struct list_head orb_list;
+	u64 management_agent_address;
+	u64 command_block_agent_address;
+	u32 workarounds;
+	int login_id;
+
+	/*
+	 * We cache these addresses and only update them once we've
+	 * logged in or reconnected to the sbp2 device.  That way, any
+	 * IO to the device will automatically fail and get retried if
+	 * it happens in a window where the device is not ready to
+	 * handle it (e.g. after a bus reset but before we reconnect).
+	 */
+	int node_id;
+	int address_high;
+	int generation;
+
+	int retries;
+	struct delayed_work work;
+};
+
+#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
+#define SBP2_MAX_SECTORS		255	/* Max sectors supported */
+#define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
+
+#define SBP2_ORB_NULL			0x80000000
+
+#define SBP2_DIRECTION_TO_MEDIA		0x0
+#define SBP2_DIRECTION_FROM_MEDIA	0x1
+
+/* Unit directory keys */
+#define SBP2_COMMAND_SET_SPECIFIER	0x38
+#define SBP2_COMMAND_SET		0x39
+#define SBP2_COMMAND_SET_REVISION	0x3b
+#define SBP2_FIRMWARE_REVISION		0x3c
+
+/* Flags for detected oddities and brokeness */
+#define SBP2_WORKAROUND_128K_MAX_TRANS	0x1
+#define SBP2_WORKAROUND_INQUIRY_36	0x2
+#define SBP2_WORKAROUND_MODE_SENSE_8	0x4
+#define SBP2_WORKAROUND_FIX_CAPACITY	0x8
+#define SBP2_WORKAROUND_OVERRIDE	0x100
+
+/* Management orb opcodes */
+#define SBP2_LOGIN_REQUEST		0x0
+#define SBP2_QUERY_LOGINS_REQUEST	0x1
+#define SBP2_RECONNECT_REQUEST		0x3
+#define SBP2_SET_PASSWORD_REQUEST	0x4
+#define SBP2_LOGOUT_REQUEST		0x7
+#define SBP2_ABORT_TASK_REQUEST		0xb
+#define SBP2_ABORT_TASK_SET		0xc
+#define SBP2_LOGICAL_UNIT_RESET		0xe
+#define SBP2_TARGET_RESET_REQUEST	0xf
+
+/* Offsets for command block agent registers */
+#define SBP2_AGENT_STATE		0x00
+#define SBP2_AGENT_RESET		0x04
+#define SBP2_ORB_POINTER		0x08
+#define SBP2_DOORBELL			0x10
+#define SBP2_UNSOLICITED_STATUS_ENABLE	0x14
+
+/* Status write response codes */
+#define SBP2_STATUS_REQUEST_COMPLETE	0x0
+#define SBP2_STATUS_TRANSPORT_FAILURE	0x1
+#define SBP2_STATUS_ILLEGAL_REQUEST	0x2
+#define SBP2_STATUS_VENDOR_DEPENDENT	0x3
+
+#define STATUS_GET_ORB_HIGH(v)		((v).status & 0xffff)
+#define STATUS_GET_SBP_STATUS(v)	(((v).status >> 16) & 0xff)
+#define STATUS_GET_LEN(v)		(((v).status >> 24) & 0x07)
+#define STATUS_GET_DEAD(v)		(((v).status >> 27) & 0x01)
+#define STATUS_GET_RESPONSE(v)		(((v).status >> 28) & 0x03)
+#define STATUS_GET_SOURCE(v)		(((v).status >> 30) & 0x03)
+#define STATUS_GET_ORB_LOW(v)		((v).orb_low)
+#define STATUS_GET_DATA(v)		((v).data)
+
+struct sbp2_status {
+	u32 status;
+	u32 orb_low;
+	u8 data[24];
+};
+
+struct sbp2_pointer {
+	u32 high;
+	u32 low;
+};
+
+struct sbp2_orb {
+	struct fw_transaction t;
+	dma_addr_t request_bus;
+	int rcode;
+	struct sbp2_pointer pointer;
+	void (*callback)(struct sbp2_orb * orb, struct sbp2_status * status);
+	struct list_head link;
+};
+
+#define MANAGEMENT_ORB_LUN(v)			((v))
+#define MANAGEMENT_ORB_FUNCTION(v)		((v) << 16)
+#define MANAGEMENT_ORB_RECONNECT(v)		((v) << 20)
+#define MANAGEMENT_ORB_EXCLUSIVE		((1) << 28)
+#define MANAGEMENT_ORB_REQUEST_FORMAT(v)	((v) << 29)
+#define MANAGEMENT_ORB_NOTIFY			((1) << 31)
+
+#define MANAGEMENT_ORB_RESPONSE_LENGTH(v)	((v))
+#define MANAGEMENT_ORB_PASSWORD_LENGTH(v)	((v) << 16)
+
+struct sbp2_management_orb {
+	struct sbp2_orb base;
+	struct {
+		struct sbp2_pointer password;
+		struct sbp2_pointer response;
+		u32 misc;
+		u32 length;
+		struct sbp2_pointer status_fifo;
+	} request;
+	__be32 response[4];
+	dma_addr_t response_bus;
+	struct completion done;
+	struct sbp2_status status;
+};
+
+#define LOGIN_RESPONSE_GET_LOGIN_ID(v)	((v).misc & 0xffff)
+#define LOGIN_RESPONSE_GET_LENGTH(v)	(((v).misc >> 16) & 0xffff)
+
+struct sbp2_login_response {
+	u32 misc;
+	struct sbp2_pointer command_block_agent;
+	u32 reconnect_hold;
+};
+#define COMMAND_ORB_DATA_SIZE(v)	((v))
+#define COMMAND_ORB_PAGE_SIZE(v)	((v) << 16)
+#define COMMAND_ORB_PAGE_TABLE_PRESENT	((1) << 19)
+#define COMMAND_ORB_MAX_PAYLOAD(v)	((v) << 20)
+#define COMMAND_ORB_SPEED(v)		((v) << 24)
+#define COMMAND_ORB_DIRECTION(v)	((v) << 27)
+#define COMMAND_ORB_REQUEST_FORMAT(v)	((v) << 29)
+#define COMMAND_ORB_NOTIFY		((1) << 31)
+
+struct sbp2_command_orb {
+	struct sbp2_orb base;
+	struct {
+		struct sbp2_pointer next;
+		struct sbp2_pointer data_descriptor;
+		u32 misc;
+		u8 command_block[12];
+	} request;
+	struct scsi_cmnd *cmd;
+	scsi_done_fn_t done;
+	struct fw_unit *unit;
+
+	struct sbp2_pointer page_table[SG_ALL];
+	dma_addr_t page_table_bus;
+	dma_addr_t request_buffer_bus;
+};
+
+/*
+ * List of devices with known bugs.
+ *
+ * The firmware_revision field, masked with 0xffff00, is the best
+ * indicator for the type of bridge chip of a device.  It yields a few
+ * false positives but this did not break correctly behaving devices
+ * so far.  We use ~0 as a wildcard, since the 24 bit values we get
+ * from the config rom can never match that.
+ */
+static const struct {
+	u32 firmware_revision;
+	u32 model;
+	unsigned workarounds;
+} sbp2_workarounds_table[] = {
+	/* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
+		.firmware_revision	= 0x002800,
+		.model			= 0x001010,
+		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 |
+					  SBP2_WORKAROUND_MODE_SENSE_8,
+	},
+	/* Initio bridges, actually only needed for some older ones */ {
+		.firmware_revision	= 0x000200,
+		.model			= ~0,
+		.workarounds		= SBP2_WORKAROUND_INQUIRY_36,
+	},
+	/* Symbios bridge */ {
+		.firmware_revision	= 0xa0b800,
+		.model			= ~0,
+		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS,
+	},
+
+	/*
+	 * There are iPods (2nd gen, 3rd gen) with model_id == 0, but
+	 * these iPods do not feature the read_capacity bug according
+	 * to one report.  Read_capacity behaviour as well as model_id
+	 * could change due to Apple-supplied firmware updates though.
+	 */
+
+	/* iPod 4th generation. */ {
+		.firmware_revision	= 0x0a2700,
+		.model			= 0x000021,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	},
+	/* iPod mini */ {
+		.firmware_revision	= 0x0a2700,
+		.model			= 0x000023,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	},
+	/* iPod Photo */ {
+		.firmware_revision	= 0x0a2700,
+		.model			= 0x00007e,
+		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY,
+	}
+};
+
+static void
+sbp2_status_write(struct fw_card *card, struct fw_request *request,
+		  int tcode, int destination, int source,
+		  int generation, int speed,
+		  unsigned long long offset,
+		  void *payload, size_t length, void *callback_data)
+{
+	struct sbp2_device *sd = callback_data;
+	struct sbp2_orb *orb;
+	struct sbp2_status status;
+	size_t header_size;
+	unsigned long flags;
+
+	if (tcode != TCODE_WRITE_BLOCK_REQUEST ||
+	    length == 0 || length > sizeof(status)) {
+		fw_send_response(card, request, RCODE_TYPE_ERROR);
+		return;
+	}
+
+	header_size = min(length, 2 * sizeof(u32));
+	fw_memcpy_from_be32(&status, payload, header_size);
+	if (length > header_size)
+		memcpy(status.data, payload + 8, length - header_size);
+	if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) {
+		fw_notify("non-orb related status write, not handled\n");
+		fw_send_response(card, request, RCODE_COMPLETE);
+		return;
+	}
+
+	/* Lookup the orb corresponding to this status write. */
+	spin_lock_irqsave(&card->lock, flags);
+	list_for_each_entry(orb, &sd->orb_list, link) {
+		if (STATUS_GET_ORB_HIGH(status) == 0 &&
+		    STATUS_GET_ORB_LOW(status) == orb->request_bus &&
+		    orb->rcode == RCODE_COMPLETE) {
+			list_del(&orb->link);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	if (&orb->link != &sd->orb_list)
+		orb->callback(orb, &status);
+	else
+		fw_error("status write for unknown orb\n");
+
+	fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+static void
+complete_transaction(struct fw_card *card, int rcode,
+		     void *payload, size_t length, void *data)
+{
+	struct sbp2_orb *orb = data;
+	unsigned long flags;
+
+	orb->rcode = rcode;
+	if (rcode != RCODE_COMPLETE) {
+		spin_lock_irqsave(&card->lock, flags);
+		list_del(&orb->link);
+		spin_unlock_irqrestore(&card->lock, flags);
+		orb->callback(orb, NULL);
+	}
+}
+
+static void
+sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
+	      int node_id, int generation, u64 offset)
+{
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_device *sd = unit->device.driver_data;
+	unsigned long flags;
+
+	orb->pointer.high = 0;
+	orb->pointer.low = orb->request_bus;
+	fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer));
+
+	spin_lock_irqsave(&device->card->lock, flags);
+	list_add_tail(&orb->link, &sd->orb_list);
+	spin_unlock_irqrestore(&device->card->lock, flags);
+
+	fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
+			node_id, generation,
+			device->node->max_speed, offset,
+			&orb->pointer, sizeof(orb->pointer),
+			complete_transaction, orb);
+}
+
+static int sbp2_cancel_orbs(struct fw_unit *unit)
+{
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_device *sd = unit->device.driver_data;
+	struct sbp2_orb *orb, *next;
+	struct list_head list;
+	unsigned long flags;
+	int retval = -ENOENT;
+
+	INIT_LIST_HEAD(&list);
+	spin_lock_irqsave(&device->card->lock, flags);
+	list_splice_init(&sd->orb_list, &list);
+	spin_unlock_irqrestore(&device->card->lock, flags);
+
+	list_for_each_entry_safe(orb, next, &list, link) {
+		retval = 0;
+		if (fw_cancel_transaction(device->card, &orb->t) == 0)
+			continue;
+
+		orb->rcode = RCODE_CANCELLED;
+		orb->callback(orb, NULL);
+	}
+
+	return retval;
+}
+
+static void
+complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
+{
+	struct sbp2_management_orb *orb =
+	    (struct sbp2_management_orb *)base_orb;
+
+	if (status)
+		memcpy(&orb->status, status, sizeof(*status));
+	complete(&orb->done);
+}
+
+static int
+sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
+			 int function, int lun, void *response)
+{
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_device *sd = unit->device.driver_data;
+	struct sbp2_management_orb *orb;
+	int retval = -ENOMEM;
+
+	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
+	if (orb == NULL)
+		return -ENOMEM;
+
+	/*
+	 * The sbp2 device is going to send a block read request to
+	 * read out the request from host memory, so map it for dma.
+	 */
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto out;
+
+	orb->response_bus =
+		dma_map_single(device->card->device, &orb->response,
+			       sizeof(orb->response), DMA_FROM_DEVICE);
+	if (dma_mapping_error(orb->response_bus))
+		goto out;
+
+	orb->request.response.high    = 0;
+	orb->request.response.low     = orb->response_bus;
+
+	orb->request.misc =
+		MANAGEMENT_ORB_NOTIFY |
+		MANAGEMENT_ORB_FUNCTION(function) |
+		MANAGEMENT_ORB_LUN(lun);
+	orb->request.length =
+		MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response));
+
+	orb->request.status_fifo.high = sd->address_handler.offset >> 32;
+	orb->request.status_fifo.low  = sd->address_handler.offset;
+
+	/*
+	 * FIXME: Yeah, ok this isn't elegant, we hardwire exclusive
+	 * login and 1 second reconnect time.  The reconnect setting
+	 * is probably fine, but the exclusive login should be an option.
+	 */
+	if (function == SBP2_LOGIN_REQUEST) {
+		orb->request.misc |=
+			MANAGEMENT_ORB_EXCLUSIVE |
+			MANAGEMENT_ORB_RECONNECT(0);
+	}
+
+	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+
+	init_completion(&orb->done);
+	orb->base.callback = complete_management_orb;
+
+	sbp2_send_orb(&orb->base, unit,
+		      node_id, generation, sd->management_agent_address);
+
+	wait_for_completion_timeout(&orb->done,
+				    msecs_to_jiffies(SBP2_ORB_TIMEOUT));
+
+	retval = -EIO;
+	if (sbp2_cancel_orbs(unit) == 0) {
+		fw_error("orb reply timed out, rcode=0x%02x\n",
+			 orb->base.rcode);
+		goto out;
+	}
+
+	if (orb->base.rcode != RCODE_COMPLETE) {
+		fw_error("management write failed, rcode 0x%02x\n",
+			 orb->base.rcode);
+		goto out;
+	}
+
+	if (STATUS_GET_RESPONSE(orb->status) != 0 ||
+	    STATUS_GET_SBP_STATUS(orb->status) != 0) {
+		fw_error("error status: %d:%d\n",
+			 STATUS_GET_RESPONSE(orb->status),
+			 STATUS_GET_SBP_STATUS(orb->status));
+		goto out;
+	}
+
+	retval = 0;
+ out:
+	dma_unmap_single(device->card->device, orb->base.request_bus,
+			 sizeof(orb->request), DMA_TO_DEVICE);
+	dma_unmap_single(device->card->device, orb->response_bus,
+			 sizeof(orb->response), DMA_FROM_DEVICE);
+
+	if (response)
+		fw_memcpy_from_be32(response,
+				    orb->response, sizeof(orb->response));
+	kfree(orb);
+
+	return retval;
+}
+
+static void
+complete_agent_reset_write(struct fw_card *card, int rcode,
+			   void *payload, size_t length, void *data)
+{
+	struct fw_transaction *t = data;
+
+	kfree(t);
+}
+
+static int sbp2_agent_reset(struct fw_unit *unit)
+{
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_device *sd = unit->device.driver_data;
+	struct fw_transaction *t;
+	static u32 zero;
+
+	t = kzalloc(sizeof(*t), GFP_ATOMIC);
+	if (t == NULL)
+		return -ENOMEM;
+
+	fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
+			sd->node_id, sd->generation, SCODE_400,
+			sd->command_block_agent_address + SBP2_AGENT_RESET,
+			&zero, sizeof(zero), complete_agent_reset_write, t);
+
+	return 0;
+}
+
+static void sbp2_reconnect(struct work_struct *work);
+static struct scsi_host_template scsi_driver_template;
+
+static void
+release_sbp2_device(struct kref *kref)
+{
+	struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
+	struct Scsi_Host *host =
+		container_of((void *)sd, struct Scsi_Host, hostdata[0]);
+
+	sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
+				 SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
+
+	scsi_remove_host(host);
+	fw_core_remove_address_handler(&sd->address_handler);
+	fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
+	put_device(&sd->unit->device);
+	scsi_host_put(host);
+}
+
+static void sbp2_login(struct work_struct *work)
+{
+	struct sbp2_device *sd =
+		container_of(work, struct sbp2_device, work.work);
+	struct Scsi_Host *host =
+		container_of((void *)sd, struct Scsi_Host, hostdata[0]);
+	struct fw_unit *unit = sd->unit;
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_login_response response;
+	int generation, node_id, local_node_id, lun, retval;
+
+	/* FIXME: Make this work for multi-lun devices. */
+	lun = 0;
+
+	generation    = device->card->generation;
+	node_id       = device->node->node_id;
+	local_node_id = device->card->local_node->node_id;
+
+	if (sbp2_send_management_orb(unit, node_id, generation,
+				     SBP2_LOGIN_REQUEST, lun, &response) < 0) {
+		if (sd->retries++ < 5) {
+			schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5));
+		} else {
+			fw_error("failed to login to %s\n",
+				 unit->device.bus_id);
+			kref_put(&sd->kref, release_sbp2_device);
+		}
+		return;
+	}
+
+	sd->generation   = generation;
+	sd->node_id      = node_id;
+	sd->address_high = local_node_id << 16;
+
+	/* Get command block agent offset and login id. */
+	sd->command_block_agent_address =
+		((u64) (response.command_block_agent.high & 0xffff) << 32) |
+		response.command_block_agent.low;
+	sd->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response);
+
+	fw_notify("logged in to sbp2 unit %s (%d retries)\n",
+		  unit->device.bus_id, sd->retries);
+	fw_notify(" - management_agent_address:    0x%012llx\n",
+		  (unsigned long long) sd->management_agent_address);
+	fw_notify(" - command_block_agent_address: 0x%012llx\n",
+		  (unsigned long long) sd->command_block_agent_address);
+	fw_notify(" - status write address:        0x%012llx\n",
+		  (unsigned long long) sd->address_handler.offset);
+
+#if 0
+	/* FIXME: The linux1394 sbp2 does this last step. */
+	sbp2_set_busy_timeout(scsi_id);
+#endif
+
+	PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect);
+	sbp2_agent_reset(unit);
+
+	/* FIXME: Loop over luns here. */
+	lun = 0;
+	retval = scsi_add_device(host, 0, 0, lun);
+	if (retval < 0) {
+		sbp2_send_management_orb(unit, sd->node_id, sd->generation,
+					 SBP2_LOGOUT_REQUEST, sd->login_id,
+					 NULL);
+		/*
+		 * Set this back to sbp2_login so we fall back and
+		 * retry login on bus reset.
+		 */
+		PREPARE_DELAYED_WORK(&sd->work, sbp2_login);
+	}
+	kref_put(&sd->kref, release_sbp2_device);
+}
+
+static int sbp2_probe(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_device *sd;
+	struct fw_csr_iterator ci;
+	struct Scsi_Host *host;
+	int i, key, value, err;
+	u32 model, firmware_revision;
+
+	err = -ENOMEM;
+	host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd));
+	if (host == NULL)
+		goto fail;
+
+	sd = (struct sbp2_device *) host->hostdata;
+	unit->device.driver_data = sd;
+	sd->unit = unit;
+	INIT_LIST_HEAD(&sd->orb_list);
+	kref_init(&sd->kref);
+
+	sd->address_handler.length = 0x100;
+	sd->address_handler.address_callback = sbp2_status_write;
+	sd->address_handler.callback_data = sd;
+
+	err = fw_core_add_address_handler(&sd->address_handler,
+					  &fw_high_memory_region);
+	if (err < 0)
+		goto fail_host;
+
+	err = fw_device_enable_phys_dma(device);
+	if (err < 0)
+		goto fail_address_handler;
+
+	err = scsi_add_host(host, &unit->device);
+	if (err < 0)
+		goto fail_address_handler;
+
+	/*
+	 * Scan unit directory to get management agent address,
+	 * firmware revison and model.  Initialize firmware_revision
+	 * and model to values that wont match anything in our table.
+	 */
+	firmware_revision = 0xff000000;
+	model = 0xff000000;
+	fw_csr_iterator_init(&ci, unit->directory);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		switch (key) {
+		case CSR_DEPENDENT_INFO | CSR_OFFSET:
+			sd->management_agent_address =
+				0xfffff0000000ULL + 4 * value;
+			break;
+		case SBP2_FIRMWARE_REVISION:
+			firmware_revision = value;
+			break;
+		case CSR_MODEL:
+			model = value;
+			break;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
+		if (sbp2_workarounds_table[i].firmware_revision !=
+		    (firmware_revision & 0xffffff00))
+			continue;
+		if (sbp2_workarounds_table[i].model != model &&
+		    sbp2_workarounds_table[i].model != ~0)
+			continue;
+		sd->workarounds |= sbp2_workarounds_table[i].workarounds;
+		break;
+	}
+
+	if (sd->workarounds)
+		fw_notify("Workarounds for node %s: 0x%x "
+			  "(firmware_revision 0x%06x, model_id 0x%06x)\n",
+			  unit->device.bus_id,
+			  sd->workarounds, firmware_revision, model);
+
+	get_device(&unit->device);
+
+	/*
+	 * We schedule work to do the login so we can easily
+	 * reschedule retries. Always get the ref before scheduling
+	 * work.
+	 */
+	INIT_DELAYED_WORK(&sd->work, sbp2_login);
+	if (schedule_delayed_work(&sd->work, 0))
+		kref_get(&sd->kref);
+
+	return 0;
+
+ fail_address_handler:
+	fw_core_remove_address_handler(&sd->address_handler);
+ fail_host:
+	scsi_host_put(host);
+ fail:
+	return err;
+}
+
+static int sbp2_remove(struct device *dev)
+{
+	struct fw_unit *unit = fw_unit(dev);
+	struct sbp2_device *sd = unit->device.driver_data;
+
+	kref_put(&sd->kref, release_sbp2_device);
+
+	return 0;
+}
+
+static void sbp2_reconnect(struct work_struct *work)
+{
+	struct sbp2_device *sd =
+		container_of(work, struct sbp2_device, work.work);
+	struct fw_unit *unit = sd->unit;
+	struct fw_device *device = fw_device(unit->device.parent);
+	int generation, node_id, local_node_id;
+
+	generation    = device->card->generation;
+	node_id       = device->node->node_id;
+	local_node_id = device->card->local_node->node_id;
+
+	if (sbp2_send_management_orb(unit, node_id, generation,
+				     SBP2_RECONNECT_REQUEST,
+				     sd->login_id, NULL) < 0) {
+		if (sd->retries++ >= 5) {
+			fw_error("failed to reconnect to %s\n",
+				 unit->device.bus_id);
+			/* Fall back and try to log in again. */
+			sd->retries = 0;
+			PREPARE_DELAYED_WORK(&sd->work, sbp2_login);
+		}
+		schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5));
+		return;
+	}
+
+	sd->generation   = generation;
+	sd->node_id      = node_id;
+	sd->address_high = local_node_id << 16;
+
+	fw_notify("reconnected to unit %s (%d retries)\n",
+		  unit->device.bus_id, sd->retries);
+	sbp2_agent_reset(unit);
+	sbp2_cancel_orbs(unit);
+	kref_put(&sd->kref, release_sbp2_device);
+}
+
+static void sbp2_update(struct fw_unit *unit)
+{
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_device *sd = unit->device.driver_data;
+
+	sd->retries = 0;
+	fw_device_enable_phys_dma(device);
+	if (schedule_delayed_work(&sd->work, 0))
+		kref_get(&sd->kref);
+}
+
+#define SBP2_UNIT_SPEC_ID_ENTRY	0x0000609e
+#define SBP2_SW_VERSION_ENTRY	0x00010483
+
+static const struct fw_device_id sbp2_id_table[] = {
+	{
+		.match_flags  = FW_MATCH_SPECIFIER_ID | FW_MATCH_VERSION,
+		.specifier_id = SBP2_UNIT_SPEC_ID_ENTRY,
+		.version      = SBP2_SW_VERSION_ENTRY,
+	},
+	{ }
+};
+
+static struct fw_driver sbp2_driver = {
+	.driver   = {
+		.owner  = THIS_MODULE,
+		.name   = sbp2_driver_name,
+		.bus    = &fw_bus_type,
+		.probe  = sbp2_probe,
+		.remove = sbp2_remove,
+	},
+	.update   = sbp2_update,
+	.id_table = sbp2_id_table,
+};
+
+static unsigned int
+sbp2_status_to_sense_data(u8 *sbp2_status, u8 *sense_data)
+{
+	int sam_status;
+
+	sense_data[0] = 0x70;
+	sense_data[1] = 0x0;
+	sense_data[2] = sbp2_status[1];
+	sense_data[3] = sbp2_status[4];
+	sense_data[4] = sbp2_status[5];
+	sense_data[5] = sbp2_status[6];
+	sense_data[6] = sbp2_status[7];
+	sense_data[7] = 10;
+	sense_data[8] = sbp2_status[8];
+	sense_data[9] = sbp2_status[9];
+	sense_data[10] = sbp2_status[10];
+	sense_data[11] = sbp2_status[11];
+	sense_data[12] = sbp2_status[2];
+	sense_data[13] = sbp2_status[3];
+	sense_data[14] = sbp2_status[12];
+	sense_data[15] = sbp2_status[13];
+
+	sam_status = sbp2_status[0] & 0x3f;
+
+	switch (sam_status) {
+	case SAM_STAT_GOOD:
+	case SAM_STAT_CHECK_CONDITION:
+	case SAM_STAT_CONDITION_MET:
+	case SAM_STAT_BUSY:
+	case SAM_STAT_RESERVATION_CONFLICT:
+	case SAM_STAT_COMMAND_TERMINATED:
+		return DID_OK << 16 | sam_status;
+
+	default:
+		return DID_ERROR << 16;
+	}
+}
+
+static void
+complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
+{
+	struct sbp2_command_orb *orb = (struct sbp2_command_orb *)base_orb;
+	struct fw_unit *unit = orb->unit;
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct scatterlist *sg;
+	int result;
+
+	if (status != NULL) {
+		if (STATUS_GET_DEAD(*status))
+			sbp2_agent_reset(unit);
+
+		switch (STATUS_GET_RESPONSE(*status)) {
+		case SBP2_STATUS_REQUEST_COMPLETE:
+			result = DID_OK << 16;
+			break;
+		case SBP2_STATUS_TRANSPORT_FAILURE:
+			result = DID_BUS_BUSY << 16;
+			break;
+		case SBP2_STATUS_ILLEGAL_REQUEST:
+		case SBP2_STATUS_VENDOR_DEPENDENT:
+		default:
+			result = DID_ERROR << 16;
+			break;
+		}
+
+		if (result == DID_OK << 16 && STATUS_GET_LEN(*status) > 1)
+			result = sbp2_status_to_sense_data(STATUS_GET_DATA(*status),
+							   orb->cmd->sense_buffer);
+	} else {
+		/*
+		 * If the orb completes with status == NULL, something
+		 * went wrong, typically a bus reset happened mid-orb
+		 * or when sending the write (less likely).
+		 */
+		result = DID_BUS_BUSY << 16;
+	}
+
+	dma_unmap_single(device->card->device, orb->base.request_bus,
+			 sizeof(orb->request), DMA_TO_DEVICE);
+
+	if (orb->cmd->use_sg > 0) {
+		sg = (struct scatterlist *)orb->cmd->request_buffer;
+		dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg,
+			     orb->cmd->sc_data_direction);
+	}
+
+	if (orb->page_table_bus != 0)
+		dma_unmap_single(device->card->device, orb->page_table_bus,
+				 sizeof(orb->page_table_bus), DMA_TO_DEVICE);
+
+	if (orb->request_buffer_bus != 0)
+		dma_unmap_single(device->card->device, orb->request_buffer_bus,
+				 sizeof(orb->request_buffer_bus),
+				 DMA_FROM_DEVICE);
+
+	orb->cmd->result = result;
+	orb->done(orb->cmd);
+	kfree(orb);
+}
+
+static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
+{
+	struct sbp2_device *sd =
+		(struct sbp2_device *)orb->cmd->device->host->hostdata;
+	struct fw_unit *unit = sd->unit;
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct scatterlist *sg;
+	int sg_len, l, i, j, count;
+	size_t size;
+	dma_addr_t sg_addr;
+
+	sg = (struct scatterlist *)orb->cmd->request_buffer;
+	count = dma_map_sg(device->card->device, sg, orb->cmd->use_sg,
+			   orb->cmd->sc_data_direction);
+	if (count == 0)
+		goto fail;
+
+	/*
+	 * Handle the special case where there is only one element in
+	 * the scatter list by converting it to an immediate block
+	 * request. This is also a workaround for broken devices such
+	 * as the second generation iPod which doesn't support page
+	 * tables.
+	 */
+	if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) {
+		orb->request.data_descriptor.high = sd->address_high;
+		orb->request.data_descriptor.low  = sg_dma_address(sg);
+		orb->request.misc |=
+			COMMAND_ORB_DATA_SIZE(sg_dma_len(sg));
+		return 0;
+	}
+
+	/*
+	 * Convert the scatterlist to an sbp2 page table.  If any
+	 * scatterlist entries are too big for sbp2, we split them as we
+	 * go.  Even if we ask the block I/O layer to not give us sg
+	 * elements larger than 65535 bytes, some IOMMUs may merge sg elements
+	 * during DMA mapping, and Linux currently doesn't prevent this.
+	 */
+	for (i = 0, j = 0; i < count; i++) {
+		sg_len = sg_dma_len(sg + i);
+		sg_addr = sg_dma_address(sg + i);
+		while (sg_len) {
+			l = min(sg_len, SBP2_MAX_SG_ELEMENT_LENGTH);
+			orb->page_table[j].low = sg_addr;
+			orb->page_table[j].high = (l << 16);
+			sg_addr += l;
+			sg_len -= l;
+			j++;
+		}
+	}
+
+	size = sizeof(orb->page_table[0]) * j;
+
+	/*
+	 * The data_descriptor pointer is the one case where we need
+	 * to fill in the node ID part of the address.  All other
+	 * pointers assume that the data referenced reside on the
+	 * initiator (i.e. us), but data_descriptor can refer to data
+	 * on other nodes so we need to put our ID in descriptor.high.
+	 */
+
+	orb->page_table_bus =
+		dma_map_single(device->card->device, orb->page_table,
+			       size, DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->page_table_bus))
+		goto fail_page_table;
+	orb->request.data_descriptor.high = sd->address_high;
+	orb->request.data_descriptor.low  = orb->page_table_bus;
+	orb->request.misc |=
+		COMMAND_ORB_PAGE_TABLE_PRESENT |
+		COMMAND_ORB_DATA_SIZE(j);
+
+	fw_memcpy_to_be32(orb->page_table, orb->page_table, size);
+
+	return 0;
+
+ fail_page_table:
+	dma_unmap_sg(device->card->device, sg, orb->cmd->use_sg,
+		     orb->cmd->sc_data_direction);
+ fail:
+	return -ENOMEM;
+}
+
+/* SCSI stack integration */
+
+static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
+{
+	struct sbp2_device *sd =
+		(struct sbp2_device *)cmd->device->host->hostdata;
+	struct fw_unit *unit = sd->unit;
+	struct fw_device *device = fw_device(unit->device.parent);
+	struct sbp2_command_orb *orb;
+
+	/*
+	 * Bidirectional commands are not yet implemented, and unknown
+	 * transfer direction not handled.
+	 */
+	if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
+		fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+		cmd->result = DID_ERROR << 16;
+		done(cmd);
+		return 0;
+	}
+
+	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
+	if (orb == NULL) {
+		fw_notify("failed to alloc orb\n");
+		goto fail_alloc;
+	}
+
+	/* Initialize rcode to something not RCODE_COMPLETE. */
+	orb->base.rcode = -1;
+	orb->base.request_bus =
+		dma_map_single(device->card->device, &orb->request,
+			       sizeof(orb->request), DMA_TO_DEVICE);
+	if (dma_mapping_error(orb->base.request_bus))
+		goto fail_mapping;
+
+	orb->unit = unit;
+	orb->done = done;
+	orb->cmd  = cmd;
+
+	orb->request.next.high   = SBP2_ORB_NULL;
+	orb->request.next.low    = 0x0;
+	/*
+	 * At speed 100 we can do 512 bytes per packet, at speed 200,
+	 * 1024 bytes per packet etc.  The SBP-2 max_payload field
+	 * specifies the max payload size as 2 ^ (max_payload + 2), so
+	 * if we set this to max_speed + 7, we get the right value.
+	 */
+	orb->request.misc =
+		COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
+		COMMAND_ORB_SPEED(device->node->max_speed) |
+		COMMAND_ORB_NOTIFY;
+
+	if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+		orb->request.misc |=
+			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_FROM_MEDIA);
+	else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+		orb->request.misc |=
+			COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA);
+
+	if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
+		goto fail_map_payload;
+
+	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+
+	memset(orb->request.command_block,
+	       0, sizeof(orb->request.command_block));
+	memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
+
+	orb->base.callback = complete_command_orb;
+
+	sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation,
+		      sd->command_block_agent_address + SBP2_ORB_POINTER);
+
+	return 0;
+
+ fail_map_payload:
+	dma_unmap_single(device->card->device, orb->base.request_bus,
+			 sizeof(orb->request), DMA_TO_DEVICE);
+ fail_mapping:
+	kfree(orb);
+ fail_alloc:
+	return SCSI_MLQUEUE_HOST_BUSY;
+}
+
+static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
+{
+	struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata;
+
+	sdev->allow_restart = 1;
+
+	if (sd->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+		sdev->inquiry_len = 36;
+	return 0;
+}
+
+static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
+{
+	struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata;
+	struct fw_unit *unit = sd->unit;
+
+	sdev->use_10_for_rw = 1;
+
+	if (sdev->type == TYPE_ROM)
+		sdev->use_10_for_ms = 1;
+	if (sdev->type == TYPE_DISK &&
+	    sd->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
+		sdev->skip_ms_page_8 = 1;
+	if (sd->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) {
+		fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
+		sdev->fix_capacity = 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Called by scsi stack when something has really gone wrong.  Usually
+ * called when a command has timed-out for some reason.
+ */
+static int sbp2_scsi_abort(struct scsi_cmnd *cmd)
+{
+	struct sbp2_device *sd =
+		(struct sbp2_device *)cmd->device->host->hostdata;
+	struct fw_unit *unit = sd->unit;
+
+	fw_notify("sbp2_scsi_abort\n");
+	sbp2_agent_reset(unit);
+	sbp2_cancel_orbs(unit);
+
+	return SUCCESS;
+}
+
+static struct scsi_host_template scsi_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "SBP-2 IEEE-1394",
+	.proc_name		= (char *)sbp2_driver_name,
+	.queuecommand		= sbp2_scsi_queuecommand,
+	.slave_alloc		= sbp2_scsi_slave_alloc,
+	.slave_configure	= sbp2_scsi_slave_configure,
+	.eh_abort_handler	= sbp2_scsi_abort,
+	.this_id		= -1,
+	.sg_tablesize		= SG_ALL,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.cmd_per_lun		= 1,
+	.can_queue		= 1,
+};
+
+MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
+MODULE_DESCRIPTION("SCSI over IEEE1394");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
+
+/* Provide a module alias so root-on-sbp2 initrds don't break. */
+#ifndef CONFIG_IEEE1394_SBP2_MODULE
+MODULE_ALIAS("sbp2");
+#endif
+
+static int __init sbp2_init(void)
+{
+	return driver_register(&sbp2_driver.driver);
+}
+
+static void __exit sbp2_cleanup(void)
+{
+	driver_unregister(&sbp2_driver.driver);
+}
+
+module_init(sbp2_init);
+module_exit(sbp2_cleanup);
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
new file mode 100644
index 0000000..7aebb8a
--- /dev/null
+++ b/drivers/firewire/fw-topology.c
@@ -0,0 +1,537 @@
+/*
+ * Incremental bus scan, based on bus topology
+ *
+ * Copyright (C) 2004-2006 Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/errno.h>
+#include "fw-transaction.h"
+#include "fw-topology.h"
+
+#define SELF_ID_PHY_ID(q)		(((q) >> 24) & 0x3f)
+#define SELF_ID_EXTENDED(q)		(((q) >> 23) & 0x01)
+#define SELF_ID_LINK_ON(q)		(((q) >> 22) & 0x01)
+#define SELF_ID_GAP_COUNT(q)		(((q) >> 16) & 0x3f)
+#define SELF_ID_PHY_SPEED(q)		(((q) >> 14) & 0x03)
+#define SELF_ID_CONTENDER(q)		(((q) >> 11) & 0x01)
+#define SELF_ID_PHY_INITIATOR(q)	(((q) >>  1) & 0x01)
+#define SELF_ID_MORE_PACKETS(q)		(((q) >>  0) & 0x01)
+
+#define SELF_ID_EXT_SEQUENCE(q)		(((q) >> 20) & 0x07)
+
+static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count)
+{
+	u32 q;
+	int port_type, shift, seq;
+
+	*total_port_count = 0;
+	*child_port_count = 0;
+
+	shift = 6;
+	q = *sid;
+	seq = 0;
+
+	while (1) {
+		port_type = (q >> shift) & 0x03;
+		switch (port_type) {
+		case SELFID_PORT_CHILD:
+			(*child_port_count)++;
+		case SELFID_PORT_PARENT:
+		case SELFID_PORT_NCONN:
+			(*total_port_count)++;
+		case SELFID_PORT_NONE:
+			break;
+		}
+
+		shift -= 2;
+		if (shift == 0) {
+			if (!SELF_ID_MORE_PACKETS(q))
+				return sid + 1;
+
+			shift = 16;
+			sid++;
+			q = *sid;
+
+			/*
+			 * Check that the extra packets actually are
+			 * extended self ID packets and that the
+			 * sequence numbers in the extended self ID
+			 * packets increase as expected.
+			 */
+
+			if (!SELF_ID_EXTENDED(q) ||
+			    seq != SELF_ID_EXT_SEQUENCE(q))
+				return NULL;
+
+			seq++;
+		}
+	}
+}
+
+static int get_port_type(u32 *sid, int port_index)
+{
+	int index, shift;
+
+	index = (port_index + 5) / 8;
+	shift = 16 - ((port_index + 5) & 7) * 2;
+	return (sid[index] >> shift) & 0x03;
+}
+
+static struct fw_node *fw_node_create(u32 sid, int port_count, int color)
+{
+	struct fw_node *node;
+
+	node = kzalloc(sizeof(*node) + port_count * sizeof(node->ports[0]),
+		       GFP_ATOMIC);
+	if (node == NULL)
+		return NULL;
+
+	node->color = color;
+	node->node_id = LOCAL_BUS | SELF_ID_PHY_ID(sid);
+	node->link_on = SELF_ID_LINK_ON(sid);
+	node->phy_speed = SELF_ID_PHY_SPEED(sid);
+	node->port_count = port_count;
+
+	atomic_set(&node->ref_count, 1);
+	INIT_LIST_HEAD(&node->link);
+
+	return node;
+}
+
+/*
+ * Compute the maximum hop count for this node and it's children.  The
+ * maximum hop count is the maximum number of connections between any
+ * two nodes in the subtree rooted at this node.  We need this for
+ * setting the gap count.  As we build the tree bottom up in
+ * build_tree() below, this is fairly easy to do: for each node we
+ * maintain the max hop count and the max depth, ie the number of hops
+ * to the furthest leaf.  Computing the max hop count breaks down into
+ * two cases: either the path goes through this node, in which case
+ * the hop count is the sum of the two biggest child depths plus 2.
+ * Or it could be the case that the max hop path is entirely
+ * containted in a child tree, in which case the max hop count is just
+ * the max hop count of this child.
+ */
+static void update_hop_count(struct fw_node *node)
+{
+	int depths[2] = { -1, -1 };
+	int max_child_hops = 0;
+	int i;
+
+	for (i = 0; i < node->port_count; i++) {
+		if (node->ports[i].node == NULL)
+			continue;
+
+		if (node->ports[i].node->max_hops > max_child_hops)
+			max_child_hops = node->ports[i].node->max_hops;
+
+		if (node->ports[i].node->max_depth > depths[0]) {
+			depths[1] = depths[0];
+			depths[0] = node->ports[i].node->max_depth;
+		} else if (node->ports[i].node->max_depth > depths[1])
+			depths[1] = node->ports[i].node->max_depth;
+	}
+
+	node->max_depth = depths[0] + 1;
+	node->max_hops = max(max_child_hops, depths[0] + depths[1] + 2);
+}
+
+
+/**
+ * build_tree - Build the tree representation of the topology
+ * @self_ids: array of self IDs to create the tree from
+ * @self_id_count: the length of the self_ids array
+ * @local_id: the node ID of the local node
+ *
+ * This function builds the tree representation of the topology given
+ * by the self IDs from the latest bus reset.  During the construction
+ * of the tree, the function checks that the self IDs are valid and
+ * internally consistent.  On succcess this funtions returns the
+ * fw_node corresponding to the local card otherwise NULL.
+ */
+static struct fw_node *build_tree(struct fw_card *card,
+				  u32 *sid, int self_id_count)
+{
+	struct fw_node *node, *child, *local_node, *irm_node;
+	struct list_head stack, *h;
+	u32 *next_sid, *end, q;
+	int i, port_count, child_port_count, phy_id, parent_count, stack_depth;
+	int gap_count, topology_type;
+
+	local_node = NULL;
+	node = NULL;
+	INIT_LIST_HEAD(&stack);
+	stack_depth = 0;
+	end = sid + self_id_count;
+	phy_id = 0;
+	irm_node = NULL;
+	gap_count = SELF_ID_GAP_COUNT(*sid);
+	topology_type = 0;
+
+	while (sid < end) {
+		next_sid = count_ports(sid, &port_count, &child_port_count);
+
+		if (next_sid == NULL) {
+			fw_error("Inconsistent extended self IDs.\n");
+			return NULL;
+		}
+
+		q = *sid;
+		if (phy_id != SELF_ID_PHY_ID(q)) {
+			fw_error("PHY ID mismatch in self ID: %d != %d.\n",
+				 phy_id, SELF_ID_PHY_ID(q));
+			return NULL;
+		}
+
+		if (child_port_count > stack_depth) {
+			fw_error("Topology stack underflow\n");
+			return NULL;
+		}
+
+		/*
+		 * Seek back from the top of our stack to find the
+		 * start of the child nodes for this node.
+		 */
+		for (i = 0, h = &stack; i < child_port_count; i++)
+			h = h->prev;
+		child = fw_node(h);
+
+		node = fw_node_create(q, port_count, card->color);
+		if (node == NULL) {
+			fw_error("Out of memory while building topology.");
+			return NULL;
+		}
+
+		if (phy_id == (card->node_id & 0x3f))
+			local_node = node;
+
+		if (SELF_ID_CONTENDER(q))
+			irm_node = node;
+
+		if (node->phy_speed == SCODE_BETA)
+			topology_type |= FW_TOPOLOGY_B;
+		else
+			topology_type |= FW_TOPOLOGY_A;
+
+		parent_count = 0;
+
+		for (i = 0; i < port_count; i++) {
+			switch (get_port_type(sid, i)) {
+			case SELFID_PORT_PARENT:
+				/*
+				 * Who's your daddy?  We dont know the
+				 * parent node at this time, so we
+				 * temporarily abuse node->color for
+				 * remembering the entry in the
+				 * node->ports array where the parent
+				 * node should be.  Later, when we
+				 * handle the parent node, we fix up
+				 * the reference.
+				 */
+				parent_count++;
+				node->color = i;
+				break;
+
+			case SELFID_PORT_CHILD:
+				node->ports[i].node = child;
+				/*
+				 * Fix up parent reference for this
+				 * child node.
+				 */
+				child->ports[child->color].node = node;
+				child->color = card->color;
+				child = fw_node(child->link.next);
+				break;
+			}
+		}
+
+		/*
+		 * Check that the node reports exactly one parent
+		 * port, except for the root, which of course should
+		 * have no parents.
+		 */
+		if ((next_sid == end && parent_count != 0) ||
+		    (next_sid < end && parent_count != 1)) {
+			fw_error("Parent port inconsistency for node %d: "
+				 "parent_count=%d\n", phy_id, parent_count);
+			return NULL;
+		}
+
+		/* Pop the child nodes off the stack and push the new node. */
+		__list_del(h->prev, &stack);
+		list_add_tail(&node->link, &stack);
+		stack_depth += 1 - child_port_count;
+
+		/*
+		 * If all PHYs does not report the same gap count
+		 * setting, we fall back to 63 which will force a gap
+		 * count reconfiguration and a reset.
+		 */
+		if (SELF_ID_GAP_COUNT(q) != gap_count)
+			gap_count = 63;
+
+		update_hop_count(node);
+
+		sid = next_sid;
+		phy_id++;
+	}
+
+	card->root_node = node;
+	card->irm_node = irm_node;
+	card->gap_count = gap_count;
+	card->topology_type = topology_type;
+
+	return local_node;
+}
+
+typedef void (*fw_node_callback_t)(struct fw_card * card,
+				   struct fw_node * node,
+				   struct fw_node * parent);
+
+static void
+for_each_fw_node(struct fw_card *card, struct fw_node *root,
+		 fw_node_callback_t callback)
+{
+	struct list_head list;
+	struct fw_node *node, *next, *child, *parent;
+	int i;
+
+	INIT_LIST_HEAD(&list);
+
+	fw_node_get(root);
+	list_add_tail(&root->link, &list);
+	parent = NULL;
+	list_for_each_entry(node, &list, link) {
+		node->color = card->color;
+
+		for (i = 0; i < node->port_count; i++) {
+			child = node->ports[i].node;
+			if (!child)
+				continue;
+			if (child->color == card->color)
+				parent = child;
+			else {
+				fw_node_get(child);
+				list_add_tail(&child->link, &list);
+			}
+		}
+
+		callback(card, node, parent);
+	}
+
+	list_for_each_entry_safe(node, next, &list, link)
+		fw_node_put(node);
+}
+
+static void
+report_lost_node(struct fw_card *card,
+		 struct fw_node *node, struct fw_node *parent)
+{
+	fw_node_event(card, node, FW_NODE_DESTROYED);
+	fw_node_put(node);
+}
+
+static void
+report_found_node(struct fw_card *card,
+		  struct fw_node *node, struct fw_node *parent)
+{
+	int b_path = (node->phy_speed == SCODE_BETA);
+
+	if (parent != NULL) {
+		/* min() macro doesn't work here with gcc 3.4 */
+		node->max_speed = parent->max_speed < node->phy_speed ?
+					parent->max_speed : node->phy_speed;
+		node->b_path = parent->b_path && b_path;
+	} else {
+		node->max_speed = node->phy_speed;
+		node->b_path = b_path;
+	}
+
+	fw_node_event(card, node, FW_NODE_CREATED);
+}
+
+void fw_destroy_nodes(struct fw_card *card)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+	card->color++;
+	if (card->local_node != NULL)
+		for_each_fw_node(card, card->local_node, report_lost_node);
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+
+static void move_tree(struct fw_node *node0, struct fw_node *node1, int port)
+{
+	struct fw_node *tree;
+	int i;
+
+	tree = node1->ports[port].node;
+	node0->ports[port].node = tree;
+	for (i = 0; i < tree->port_count; i++) {
+		if (tree->ports[i].node == node1) {
+			tree->ports[i].node = node0;
+			break;
+		}
+	}
+}
+
+/**
+ * update_tree - compare the old topology tree for card with the new
+ * one specified by root.  Queue the nodes and mark them as either
+ * found, lost or updated.  Update the nodes in the card topology tree
+ * as we go.
+ */
+static void
+update_tree(struct fw_card *card, struct fw_node *root)
+{
+	struct list_head list0, list1;
+	struct fw_node *node0, *node1;
+	int i, event;
+
+	INIT_LIST_HEAD(&list0);
+	list_add_tail(&card->local_node->link, &list0);
+	INIT_LIST_HEAD(&list1);
+	list_add_tail(&root->link, &list1);
+
+	node0 = fw_node(list0.next);
+	node1 = fw_node(list1.next);
+
+	while (&node0->link != &list0) {
+
+		/* assert(node0->port_count == node1->port_count); */
+		if (node0->link_on && !node1->link_on)
+			event = FW_NODE_LINK_OFF;
+		else if (!node0->link_on && node1->link_on)
+			event = FW_NODE_LINK_ON;
+		else
+			event = FW_NODE_UPDATED;
+
+		node0->node_id = node1->node_id;
+		node0->color = card->color;
+		node0->link_on = node1->link_on;
+		node0->initiated_reset = node1->initiated_reset;
+		node0->max_hops = node1->max_hops;
+		node1->color = card->color;
+		fw_node_event(card, node0, event);
+
+		if (card->root_node == node1)
+			card->root_node = node0;
+		if (card->irm_node == node1)
+			card->irm_node = node0;
+
+		for (i = 0; i < node0->port_count; i++) {
+			if (node0->ports[i].node && node1->ports[i].node) {
+				/*
+				 * This port didn't change, queue the
+				 * connected node for further
+				 * investigation.
+				 */
+				if (node0->ports[i].node->color == card->color)
+					continue;
+				list_add_tail(&node0->ports[i].node->link,
+					      &list0);
+				list_add_tail(&node1->ports[i].node->link,
+					      &list1);
+			} else if (node0->ports[i].node) {
+				/*
+				 * The nodes connected here were
+				 * unplugged; unref the lost nodes and
+				 * queue FW_NODE_LOST callbacks for
+				 * them.
+				 */
+
+				for_each_fw_node(card, node0->ports[i].node,
+						 report_lost_node);
+				node0->ports[i].node = NULL;
+			} else if (node1->ports[i].node) {
+				/*
+				 * One or more node were connected to
+				 * this port. Move the new nodes into
+				 * the tree and queue FW_NODE_CREATED
+				 * callbacks for them.
+				 */
+				move_tree(node0, node1, i);
+				for_each_fw_node(card, node0->ports[i].node,
+						 report_found_node);
+			}
+		}
+
+		node0 = fw_node(node0->link.next);
+		node1 = fw_node(node1->link.next);
+	}
+}
+
+static void
+update_topology_map(struct fw_card *card, u32 *self_ids, int self_id_count)
+{
+	int node_count;
+
+	card->topology_map[1]++;
+	node_count = (card->root_node->node_id & 0x3f) + 1;
+	card->topology_map[2] = (node_count << 16) | self_id_count;
+	card->topology_map[0] = (self_id_count + 2) << 16;
+	memcpy(&card->topology_map[3], self_ids, self_id_count * 4);
+	fw_compute_block_crc(card->topology_map);
+}
+
+void
+fw_core_handle_bus_reset(struct fw_card *card,
+			 int node_id, int generation,
+			 int self_id_count, u32 * self_ids)
+{
+	struct fw_node *local_node;
+	unsigned long flags;
+
+	fw_flush_transactions(card);
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	/*
+	 * If the new topology has a different self_id_count the topology
+	 * changed, either nodes were added or removed. In that case we
+	 * reset the IRM reset counter.
+	 */
+	if (card->self_id_count != self_id_count)
+		card->bm_retries = 0;
+
+	card->node_id = node_id;
+	card->generation = generation;
+	card->reset_jiffies = jiffies;
+	schedule_delayed_work(&card->work, 0);
+
+	local_node = build_tree(card, self_ids, self_id_count);
+
+	update_topology_map(card, self_ids, self_id_count);
+
+	card->color++;
+
+	if (local_node == NULL) {
+		fw_error("topology build failed\n");
+		/* FIXME: We need to issue a bus reset in this case. */
+	} else if (card->local_node == NULL) {
+		card->local_node = local_node;
+		for_each_fw_node(card, local_node, report_found_node);
+	} else {
+		update_tree(card, local_node);
+	}
+
+	spin_unlock_irqrestore(&card->lock, flags);
+}
+EXPORT_SYMBOL(fw_core_handle_bus_reset);
diff --git a/drivers/firewire/fw-topology.h b/drivers/firewire/fw-topology.h
new file mode 100644
index 0000000..363b6cb
--- /dev/null
+++ b/drivers/firewire/fw-topology.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __fw_topology_h
+#define __fw_topology_h
+
+enum {
+	FW_TOPOLOGY_A =		0x01,
+	FW_TOPOLOGY_B =		0x02,
+	FW_TOPOLOGY_MIXED =	0x03,
+};
+
+enum {
+	FW_NODE_CREATED =   0x00,
+	FW_NODE_UPDATED =   0x01,
+	FW_NODE_DESTROYED = 0x02,
+	FW_NODE_LINK_ON =   0x03,
+	FW_NODE_LINK_OFF =  0x04,
+};
+
+struct fw_port {
+	struct fw_node *node;
+	unsigned speed : 3; /* S100, S200, ... S3200 */
+};
+
+struct fw_node {
+	u16 node_id;
+	u8 color;
+	u8 port_count;
+	unsigned link_on : 1;
+	unsigned initiated_reset : 1;
+	unsigned b_path : 1;
+	u8 phy_speed : 3; /* As in the self ID packet. */
+	u8 max_speed : 5; /* Minimum of all phy-speeds and port speeds on
+			   * the path from the local node to this node. */
+	u8 max_depth : 4; /* Maximum depth to any leaf node */
+	u8 max_hops : 4;  /* Max hops in this sub tree */
+	atomic_t ref_count;
+
+	/* For serializing node topology into a list. */
+	struct list_head link;
+
+	/* Upper layer specific data. */
+	void *data;
+
+	struct fw_port ports[0];
+};
+
+static inline struct fw_node *
+fw_node(struct list_head *l)
+{
+	return list_entry(l, struct fw_node, link);
+}
+
+static inline struct fw_node *
+fw_node_get(struct fw_node *node)
+{
+	atomic_inc(&node->ref_count);
+
+	return node;
+}
+
+static inline void
+fw_node_put(struct fw_node *node)
+{
+	if (atomic_dec_and_test(&node->ref_count))
+		kfree(node);
+}
+
+void
+fw_destroy_nodes(struct fw_card *card);
+
+int
+fw_compute_block_crc(u32 *block);
+
+
+#endif /* __fw_topology_h */
diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
new file mode 100644
index 0000000..80d0121
--- /dev/null
+++ b/drivers/firewire/fw-transaction.c
@@ -0,0 +1,910 @@
+/*
+ * Core IEEE1394 transaction logic
+ *
+ * Copyright (C) 2004-2006 Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/poll.h>
+#include <linux/list.h>
+#include <linux/kthread.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "fw-transaction.h"
+#include "fw-topology.h"
+#include "fw-device.h"
+
+#define HEADER_PRI(pri)			((pri) << 0)
+#define HEADER_TCODE(tcode)		((tcode) << 4)
+#define HEADER_RETRY(retry)		((retry) << 8)
+#define HEADER_TLABEL(tlabel)		((tlabel) << 10)
+#define HEADER_DESTINATION(destination)	((destination) << 16)
+#define HEADER_SOURCE(source)		((source) << 16)
+#define HEADER_RCODE(rcode)		((rcode) << 12)
+#define HEADER_OFFSET_HIGH(offset_high)	((offset_high) << 0)
+#define HEADER_DATA_LENGTH(length)	((length) << 16)
+#define HEADER_EXTENDED_TCODE(tcode)	((tcode) << 0)
+
+#define HEADER_GET_TCODE(q)		(((q) >> 4) & 0x0f)
+#define HEADER_GET_TLABEL(q)		(((q) >> 10) & 0x3f)
+#define HEADER_GET_RCODE(q)		(((q) >> 12) & 0x0f)
+#define HEADER_GET_DESTINATION(q)	(((q) >> 16) & 0xffff)
+#define HEADER_GET_SOURCE(q)		(((q) >> 16) & 0xffff)
+#define HEADER_GET_OFFSET_HIGH(q)	(((q) >> 0) & 0xffff)
+#define HEADER_GET_DATA_LENGTH(q)	(((q) >> 16) & 0xffff)
+#define HEADER_GET_EXTENDED_TCODE(q)	(((q) >> 0) & 0xffff)
+
+#define PHY_CONFIG_GAP_COUNT(gap_count)	(((gap_count) << 16) | (1 << 22))
+#define PHY_CONFIG_ROOT_ID(node_id)	((((node_id) & 0x3f) << 24) | (1 << 23))
+#define PHY_IDENTIFIER(id)		((id) << 30)
+
+static int
+close_transaction(struct fw_transaction *transaction,
+		  struct fw_card *card, int rcode,
+		  u32 *payload, size_t length)
+{
+	struct fw_transaction *t;
+	unsigned long flags;
+
+	spin_lock_irqsave(&card->lock, flags);
+	list_for_each_entry(t, &card->transaction_list, link) {
+		if (t == transaction) {
+			list_del(&t->link);
+			card->tlabel_mask &= ~(1 << t->tlabel);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	if (&t->link != &card->transaction_list) {
+		t->callback(card, rcode, payload, length, t->callback_data);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+/*
+ * Only valid for transactions that are potentially pending (ie have
+ * been sent).
+ */
+int
+fw_cancel_transaction(struct fw_card *card,
+		      struct fw_transaction *transaction)
+{
+	/*
+	 * Cancel the packet transmission if it's still queued.  That
+	 * will call the packet transmission callback which cancels
+	 * the transaction.
+	 */
+
+	if (card->driver->cancel_packet(card, &transaction->packet) == 0)
+		return 0;
+
+	/*
+	 * If the request packet has already been sent, we need to see
+	 * if the transaction is still pending and remove it in that case.
+	 */
+
+	return close_transaction(transaction, card, RCODE_CANCELLED, NULL, 0);
+}
+EXPORT_SYMBOL(fw_cancel_transaction);
+
+static void
+transmit_complete_callback(struct fw_packet *packet,
+			   struct fw_card *card, int status)
+{
+	struct fw_transaction *t =
+	    container_of(packet, struct fw_transaction, packet);
+
+	switch (status) {
+	case ACK_COMPLETE:
+		close_transaction(t, card, RCODE_COMPLETE, NULL, 0);
+		break;
+	case ACK_PENDING:
+		t->timestamp = packet->timestamp;
+		break;
+	case ACK_BUSY_X:
+	case ACK_BUSY_A:
+	case ACK_BUSY_B:
+		close_transaction(t, card, RCODE_BUSY, NULL, 0);
+		break;
+	case ACK_DATA_ERROR:
+		close_transaction(t, card, RCODE_DATA_ERROR, NULL, 0);
+		break;
+	case ACK_TYPE_ERROR:
+		close_transaction(t, card, RCODE_TYPE_ERROR, NULL, 0);
+		break;
+	default:
+		/*
+		 * In this case the ack is really a juju specific
+		 * rcode, so just forward that to the callback.
+		 */
+		close_transaction(t, card, status, NULL, 0);
+		break;
+	}
+}
+
+static void
+fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
+		int node_id, int source_id, int generation, int speed,
+		unsigned long long offset, void *payload, size_t length)
+{
+	int ext_tcode;
+
+	if (tcode > 0x10) {
+		ext_tcode = tcode - 0x10;
+		tcode = TCODE_LOCK_REQUEST;
+	} else
+		ext_tcode = 0;
+
+	packet->header[0] =
+		HEADER_RETRY(RETRY_X) |
+		HEADER_TLABEL(tlabel) |
+		HEADER_TCODE(tcode) |
+		HEADER_DESTINATION(node_id);
+	packet->header[1] =
+		HEADER_OFFSET_HIGH(offset >> 32) | HEADER_SOURCE(source_id);
+	packet->header[2] =
+		offset;
+
+	switch (tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+		packet->header[3] = *(u32 *)payload;
+		packet->header_length = 16;
+		packet->payload_length = 0;
+		break;
+
+	case TCODE_LOCK_REQUEST:
+	case TCODE_WRITE_BLOCK_REQUEST:
+		packet->header[3] =
+			HEADER_DATA_LENGTH(length) |
+			HEADER_EXTENDED_TCODE(ext_tcode);
+		packet->header_length = 16;
+		packet->payload = payload;
+		packet->payload_length = length;
+		break;
+
+	case TCODE_READ_QUADLET_REQUEST:
+		packet->header_length = 12;
+		packet->payload_length = 0;
+		break;
+
+	case TCODE_READ_BLOCK_REQUEST:
+		packet->header[3] =
+			HEADER_DATA_LENGTH(length) |
+			HEADER_EXTENDED_TCODE(ext_tcode);
+		packet->header_length = 16;
+		packet->payload_length = 0;
+		break;
+	}
+
+	packet->speed = speed;
+	packet->generation = generation;
+	packet->ack = 0;
+}
+
+/**
+ * This function provides low-level access to the IEEE1394 transaction
+ * logic.  Most C programs would use either fw_read(), fw_write() or
+ * fw_lock() instead - those function are convenience wrappers for
+ * this function.  The fw_send_request() function is primarily
+ * provided as a flexible, one-stop entry point for languages bindings
+ * and protocol bindings.
+ *
+ * FIXME: Document this function further, in particular the possible
+ * values for rcode in the callback.  In short, we map ACK_COMPLETE to
+ * RCODE_COMPLETE, internal errors set errno and set rcode to
+ * RCODE_SEND_ERROR (which is out of range for standard ieee1394
+ * rcodes).  All other rcodes are forwarded unchanged.  For all
+ * errors, payload is NULL, length is 0.
+ *
+ * Can not expect the callback to be called before the function
+ * returns, though this does happen in some cases (ACK_COMPLETE and
+ * errors).
+ *
+ * The payload is only used for write requests and must not be freed
+ * until the callback has been called.
+ *
+ * @param card the card from which to send the request
+ * @param tcode the tcode for this transaction.  Do not use
+ *   TCODE_LOCK_REQUEST directly, insted use TCODE_LOCK_MASK_SWAP
+ *   etc. to specify tcode and ext_tcode.
+ * @param node_id the destination node ID (bus ID and PHY ID concatenated)
+ * @param generation the generation for which node_id is valid
+ * @param speed the speed to use for sending the request
+ * @param offset the 48 bit offset on the destination node
+ * @param payload the data payload for the request subaction
+ * @param length the length in bytes of the data to read
+ * @param callback function to be called when the transaction is completed
+ * @param callback_data pointer to arbitrary data, which will be
+ *   passed to the callback
+ */
+void
+fw_send_request(struct fw_card *card, struct fw_transaction *t,
+		int tcode, int node_id, int generation, int speed,
+		unsigned long long offset,
+		void *payload, size_t length,
+		fw_transaction_callback_t callback, void *callback_data)
+{
+	unsigned long flags;
+	int tlabel, source;
+
+	/*
+	 * Bump the flush timer up 100ms first of all so we
+	 * don't race with a flush timer callback.
+	 */
+
+	mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10));
+
+	/*
+	 * Allocate tlabel from the bitmap and put the transaction on
+	 * the list while holding the card spinlock.
+	 */
+
+	spin_lock_irqsave(&card->lock, flags);
+
+	source = card->node_id;
+	tlabel = card->current_tlabel;
+	if (card->tlabel_mask & (1 << tlabel)) {
+		spin_unlock_irqrestore(&card->lock, flags);
+		callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data);
+		return;
+	}
+
+	card->current_tlabel = (card->current_tlabel + 1) & 0x1f;
+	card->tlabel_mask |= (1 << tlabel);
+
+	list_add_tail(&t->link, &card->transaction_list);
+
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	/* Initialize rest of transaction, fill out packet and send it. */
+	t->node_id = node_id;
+	t->tlabel = tlabel;
+	t->callback = callback;
+	t->callback_data = callback_data;
+
+	fw_fill_request(&t->packet, tcode, t->tlabel,
+			node_id, source, generation,
+			speed, offset, payload, length);
+	t->packet.callback = transmit_complete_callback;
+
+	card->driver->send_request(card, &t->packet);
+}
+EXPORT_SYMBOL(fw_send_request);
+
+static void
+transmit_phy_packet_callback(struct fw_packet *packet,
+			     struct fw_card *card, int status)
+{
+	kfree(packet);
+}
+
+static void send_phy_packet(struct fw_card *card, u32 data, int generation)
+{
+	struct fw_packet *packet;
+
+	packet = kzalloc(sizeof(*packet), GFP_ATOMIC);
+	if (packet == NULL)
+		return;
+
+	packet->header[0] = data;
+	packet->header[1] = ~data;
+	packet->header_length = 8;
+	packet->payload_length = 0;
+	packet->speed = SCODE_100;
+	packet->generation = generation;
+	packet->callback = transmit_phy_packet_callback;
+
+	card->driver->send_request(card, packet);
+}
+
+void fw_send_phy_config(struct fw_card *card,
+			int node_id, int generation, int gap_count)
+{
+	u32 q;
+
+	q = PHY_IDENTIFIER(PHY_PACKET_CONFIG) |
+		PHY_CONFIG_ROOT_ID(node_id) |
+		PHY_CONFIG_GAP_COUNT(gap_count);
+
+	send_phy_packet(card, q, generation);
+}
+
+void fw_flush_transactions(struct fw_card *card)
+{
+	struct fw_transaction *t, *next;
+	struct list_head list;
+	unsigned long flags;
+
+	INIT_LIST_HEAD(&list);
+	spin_lock_irqsave(&card->lock, flags);
+	list_splice_init(&card->transaction_list, &list);
+	card->tlabel_mask = 0;
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	list_for_each_entry_safe(t, next, &list, link) {
+		card->driver->cancel_packet(card, &t->packet);
+
+		/*
+		 * At this point cancel_packet will never call the
+		 * transaction callback, since we just took all the
+		 * transactions out of the list.  So do it here.
+		 */
+		t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data);
+	}
+}
+
+static struct fw_address_handler *
+lookup_overlapping_address_handler(struct list_head *list,
+				   unsigned long long offset, size_t length)
+{
+	struct fw_address_handler *handler;
+
+	list_for_each_entry(handler, list, link) {
+		if (handler->offset < offset + length &&
+		    offset < handler->offset + handler->length)
+			return handler;
+	}
+
+	return NULL;
+}
+
+static struct fw_address_handler *
+lookup_enclosing_address_handler(struct list_head *list,
+				 unsigned long long offset, size_t length)
+{
+	struct fw_address_handler *handler;
+
+	list_for_each_entry(handler, list, link) {
+		if (handler->offset <= offset &&
+		    offset + length <= handler->offset + handler->length)
+			return handler;
+	}
+
+	return NULL;
+}
+
+static DEFINE_SPINLOCK(address_handler_lock);
+static LIST_HEAD(address_handler_list);
+
+const struct fw_address_region fw_low_memory_region =
+	{ .start = 0x000000000000ULL, .end = 0x000100000000ULL,  };
+const struct fw_address_region fw_high_memory_region =
+	{ .start = 0x000100000000ULL, .end = 0xffffe0000000ULL,  };
+const struct fw_address_region fw_private_region =
+	{ .start = 0xffffe0000000ULL, .end = 0xfffff0000000ULL,  };
+const struct fw_address_region fw_csr_region =
+	{ .start = 0xfffff0000000ULL, .end = 0xfffff0000800ULL,  };
+const struct fw_address_region fw_unit_space_region =
+	{ .start = 0xfffff0000900ULL, .end = 0x1000000000000ULL, };
+EXPORT_SYMBOL(fw_low_memory_region);
+EXPORT_SYMBOL(fw_high_memory_region);
+EXPORT_SYMBOL(fw_private_region);
+EXPORT_SYMBOL(fw_csr_region);
+EXPORT_SYMBOL(fw_unit_space_region);
+
+/**
+ * Allocate a range of addresses in the node space of the OHCI
+ * controller.  When a request is received that falls within the
+ * specified address range, the specified callback is invoked.  The
+ * parameters passed to the callback give the details of the
+ * particular request
+ */
+int
+fw_core_add_address_handler(struct fw_address_handler *handler,
+			    const struct fw_address_region *region)
+{
+	struct fw_address_handler *other;
+	unsigned long flags;
+	int ret = -EBUSY;
+
+	spin_lock_irqsave(&address_handler_lock, flags);
+
+	handler->offset = region->start;
+	while (handler->offset + handler->length <= region->end) {
+		other =
+		    lookup_overlapping_address_handler(&address_handler_list,
+						       handler->offset,
+						       handler->length);
+		if (other != NULL) {
+			handler->offset += other->length;
+		} else {
+			list_add_tail(&handler->link, &address_handler_list);
+			ret = 0;
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&address_handler_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(fw_core_add_address_handler);
+
+/**
+ * Deallocate a range of addresses allocated with fw_allocate.  This
+ * will call the associated callback one last time with a the special
+ * tcode TCODE_DEALLOCATE, to let the client destroy the registered
+ * callback data.  For convenience, the callback parameters offset and
+ * length are set to the start and the length respectively for the
+ * deallocated region, payload is set to NULL.
+ */
+void fw_core_remove_address_handler(struct fw_address_handler *handler)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&address_handler_lock, flags);
+	list_del(&handler->link);
+	spin_unlock_irqrestore(&address_handler_lock, flags);
+}
+EXPORT_SYMBOL(fw_core_remove_address_handler);
+
+struct fw_request {
+	struct fw_packet response;
+	u32 request_header[4];
+	int ack;
+	u32 length;
+	u32 data[0];
+};
+
+static void
+free_response_callback(struct fw_packet *packet,
+		       struct fw_card *card, int status)
+{
+	struct fw_request *request;
+
+	request = container_of(packet, struct fw_request, response);
+	kfree(request);
+}
+
+void
+fw_fill_response(struct fw_packet *response, u32 *request_header,
+		 int rcode, void *payload, size_t length)
+{
+	int tcode, tlabel, extended_tcode, source, destination;
+
+	tcode          = HEADER_GET_TCODE(request_header[0]);
+	tlabel         = HEADER_GET_TLABEL(request_header[0]);
+	source         = HEADER_GET_DESTINATION(request_header[0]);
+	destination    = HEADER_GET_SOURCE(request_header[1]);
+	extended_tcode = HEADER_GET_EXTENDED_TCODE(request_header[3]);
+
+	response->header[0] =
+		HEADER_RETRY(RETRY_1) |
+		HEADER_TLABEL(tlabel) |
+		HEADER_DESTINATION(destination);
+	response->header[1] =
+		HEADER_SOURCE(source) |
+		HEADER_RCODE(rcode);
+	response->header[2] = 0;
+
+	switch (tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+	case TCODE_WRITE_BLOCK_REQUEST:
+		response->header[0] |= HEADER_TCODE(TCODE_WRITE_RESPONSE);
+		response->header_length = 12;
+		response->payload_length = 0;
+		break;
+
+	case TCODE_READ_QUADLET_REQUEST:
+		response->header[0] |=
+			HEADER_TCODE(TCODE_READ_QUADLET_RESPONSE);
+		if (payload != NULL)
+			response->header[3] = *(u32 *)payload;
+		else
+			response->header[3] = 0;
+		response->header_length = 16;
+		response->payload_length = 0;
+		break;
+
+	case TCODE_READ_BLOCK_REQUEST:
+	case TCODE_LOCK_REQUEST:
+		response->header[0] |= HEADER_TCODE(tcode + 2);
+		response->header[3] =
+			HEADER_DATA_LENGTH(length) |
+			HEADER_EXTENDED_TCODE(extended_tcode);
+		response->header_length = 16;
+		response->payload = payload;
+		response->payload_length = length;
+		break;
+
+	default:
+		BUG();
+		return;
+	}
+}
+EXPORT_SYMBOL(fw_fill_response);
+
+static struct fw_request *
+allocate_request(struct fw_packet *p)
+{
+	struct fw_request *request;
+	u32 *data, length;
+	int request_tcode, t;
+
+	request_tcode = HEADER_GET_TCODE(p->header[0]);
+	switch (request_tcode) {
+	case TCODE_WRITE_QUADLET_REQUEST:
+		data = &p->header[3];
+		length = 4;
+		break;
+
+	case TCODE_WRITE_BLOCK_REQUEST:
+	case TCODE_LOCK_REQUEST:
+		data = p->payload;
+		length = HEADER_GET_DATA_LENGTH(p->header[3]);
+		break;
+
+	case TCODE_READ_QUADLET_REQUEST:
+		data = NULL;
+		length = 4;
+		break;
+
+	case TCODE_READ_BLOCK_REQUEST:
+		data = NULL;
+		length = HEADER_GET_DATA_LENGTH(p->header[3]);
+		break;
+
+	default:
+		BUG();
+		return NULL;
+	}
+
+	request = kmalloc(sizeof(*request) + length, GFP_ATOMIC);
+	if (request == NULL)
+		return NULL;
+
+	t = (p->timestamp & 0x1fff) + 4000;
+	if (t >= 8000)
+		t = (p->timestamp & ~0x1fff) + 0x2000 + t - 8000;
+	else
+		t = (p->timestamp & ~0x1fff) + t;
+
+	request->response.speed = p->speed;
+	request->response.timestamp = t;
+	request->response.generation = p->generation;
+	request->response.ack = 0;
+	request->response.callback = free_response_callback;
+	request->ack = p->ack;
+	request->length = length;
+	if (data)
+		memcpy(request->data, data, length);
+
+	memcpy(request->request_header, p->header, sizeof(p->header));
+
+	return request;
+}
+
+void
+fw_send_response(struct fw_card *card, struct fw_request *request, int rcode)
+{
+	/*
+	 * Broadcast packets are reported as ACK_COMPLETE, so this
+	 * check is sufficient to ensure we don't send response to
+	 * broadcast packets or posted writes.
+	 */
+	if (request->ack != ACK_PENDING)
+		return;
+
+	if (rcode == RCODE_COMPLETE)
+		fw_fill_response(&request->response, request->request_header,
+				 rcode, request->data, request->length);
+	else
+		fw_fill_response(&request->response, request->request_header,
+				 rcode, NULL, 0);
+
+	card->driver->send_response(card, &request->response);
+}
+EXPORT_SYMBOL(fw_send_response);
+
+void
+fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
+{
+	struct fw_address_handler *handler;
+	struct fw_request *request;
+	unsigned long long offset;
+	unsigned long flags;
+	int tcode, destination, source;
+
+	if (p->payload_length > 2048) {
+		/* FIXME: send error response. */
+		return;
+	}
+
+	if (p->ack != ACK_PENDING && p->ack != ACK_COMPLETE)
+		return;
+
+	request = allocate_request(p);
+	if (request == NULL) {
+		/* FIXME: send statically allocated busy packet. */
+		return;
+	}
+
+	offset      =
+		((unsigned long long)
+		 HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2];
+	tcode       = HEADER_GET_TCODE(p->header[0]);
+	destination = HEADER_GET_DESTINATION(p->header[0]);
+	source      = HEADER_GET_SOURCE(p->header[0]);
+
+	spin_lock_irqsave(&address_handler_lock, flags);
+	handler = lookup_enclosing_address_handler(&address_handler_list,
+						   offset, request->length);
+	spin_unlock_irqrestore(&address_handler_lock, flags);
+
+	/*
+	 * FIXME: lookup the fw_node corresponding to the sender of
+	 * this request and pass that to the address handler instead
+	 * of the node ID.  We may also want to move the address
+	 * allocations to fw_node so we only do this callback if the
+	 * upper layers registered it for this node.
+	 */
+
+	if (handler == NULL)
+		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+	else
+		handler->address_callback(card, request,
+					  tcode, destination, source,
+					  p->generation, p->speed, offset,
+					  request->data, request->length,
+					  handler->callback_data);
+}
+EXPORT_SYMBOL(fw_core_handle_request);
+
+void
+fw_core_handle_response(struct fw_card *card, struct fw_packet *p)
+{
+	struct fw_transaction *t;
+	unsigned long flags;
+	u32 *data;
+	size_t data_length;
+	int tcode, tlabel, destination, source, rcode;
+
+	tcode       = HEADER_GET_TCODE(p->header[0]);
+	tlabel      = HEADER_GET_TLABEL(p->header[0]);
+	destination = HEADER_GET_DESTINATION(p->header[0]);
+	source      = HEADER_GET_SOURCE(p->header[1]);
+	rcode       = HEADER_GET_RCODE(p->header[1]);
+
+	spin_lock_irqsave(&card->lock, flags);
+	list_for_each_entry(t, &card->transaction_list, link) {
+		if (t->node_id == source && t->tlabel == tlabel) {
+			list_del(&t->link);
+			card->tlabel_mask &= ~(1 << t->tlabel);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&card->lock, flags);
+
+	if (&t->link == &card->transaction_list) {
+		fw_notify("Unsolicited response (source %x, tlabel %x)\n",
+			  source, tlabel);
+		return;
+	}
+
+	/*
+	 * FIXME: sanity check packet, is length correct, does tcodes
+	 * and addresses match.
+	 */
+
+	switch (tcode) {
+	case TCODE_READ_QUADLET_RESPONSE:
+		data = (u32 *) &p->header[3];
+		data_length = 4;
+		break;
+
+	case TCODE_WRITE_RESPONSE:
+		data = NULL;
+		data_length = 0;
+		break;
+
+	case TCODE_READ_BLOCK_RESPONSE:
+	case TCODE_LOCK_RESPONSE:
+		data = p->payload;
+		data_length = HEADER_GET_DATA_LENGTH(p->header[3]);
+		break;
+
+	default:
+		/* Should never happen, this is just to shut up gcc. */
+		data = NULL;
+		data_length = 0;
+		break;
+	}
+
+	t->callback(card, rcode, data, data_length, t->callback_data);
+}
+EXPORT_SYMBOL(fw_core_handle_response);
+
+const struct fw_address_region topology_map_region =
+	{ .start = 0xfffff0001000ull, .end = 0xfffff0001400ull, };
+
+static void
+handle_topology_map(struct fw_card *card, struct fw_request *request,
+		    int tcode, int destination, int source,
+		    int generation, int speed,
+		    unsigned long long offset,
+		    void *payload, size_t length, void *callback_data)
+{
+	int i, start, end;
+	u32 *map;
+
+	if (!TCODE_IS_READ_REQUEST(tcode)) {
+		fw_send_response(card, request, RCODE_TYPE_ERROR);
+		return;
+	}
+
+	if ((offset & 3) > 0 || (length & 3) > 0) {
+		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+		return;
+	}
+
+	start = (offset - topology_map_region.start) / 4;
+	end = start + length / 4;
+	map = payload;
+
+	for (i = 0; i < length / 4; i++)
+		map[i] = cpu_to_be32(card->topology_map[start + i]);
+
+	fw_send_response(card, request, RCODE_COMPLETE);
+}
+
+static struct fw_address_handler topology_map = {
+	.length			= 0x200,
+	.address_callback	= handle_topology_map,
+};
+
+const struct fw_address_region registers_region =
+	{ .start = 0xfffff0000000ull, .end = 0xfffff0000400ull, };
+
+static void
+handle_registers(struct fw_card *card, struct fw_request *request,
+		 int tcode, int destination, int source,
+		 int generation, int speed,
+		 unsigned long long offset,
+		 void *payload, size_t length, void *callback_data)
+{
+	int reg = offset - CSR_REGISTER_BASE;
+	unsigned long long bus_time;
+	__be32 *data = payload;
+
+	switch (reg) {
+	case CSR_CYCLE_TIME:
+	case CSR_BUS_TIME:
+		if (!TCODE_IS_READ_REQUEST(tcode) || length != 4) {
+			fw_send_response(card, request, RCODE_TYPE_ERROR);
+			break;
+		}
+
+		bus_time = card->driver->get_bus_time(card);
+		if (reg == CSR_CYCLE_TIME)
+			*data = cpu_to_be32(bus_time);
+		else
+			*data = cpu_to_be32(bus_time >> 25);
+		fw_send_response(card, request, RCODE_COMPLETE);
+		break;
+
+	case CSR_BUS_MANAGER_ID:
+	case CSR_BANDWIDTH_AVAILABLE:
+	case CSR_CHANNELS_AVAILABLE_HI:
+	case CSR_CHANNELS_AVAILABLE_LO:
+		/*
+		 * FIXME: these are handled by the OHCI hardware and
+		 * the stack never sees these request. If we add
+		 * support for a new type of controller that doesn't
+		 * handle this in hardware we need to deal with these
+		 * transactions.
+		 */
+		BUG();
+		break;
+
+	case CSR_BUSY_TIMEOUT:
+		/* FIXME: Implement this. */
+	default:
+		fw_send_response(card, request, RCODE_ADDRESS_ERROR);
+		break;
+	}
+}
+
+static struct fw_address_handler registers = {
+	.length			= 0x400,
+	.address_callback	= handle_registers,
+};
+
+MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");
+MODULE_DESCRIPTION("Core IEEE1394 transaction logic");
+MODULE_LICENSE("GPL");
+
+static const u32 vendor_textual_descriptor[] = {
+	/* textual descriptor leaf () */
+	0x00060000,
+	0x00000000,
+	0x00000000,
+	0x4c696e75,		/* L i n u */
+	0x78204669,		/* x   F i */
+	0x72657769,		/* r e w i */
+	0x72650000,		/* r e     */
+};
+
+static const u32 model_textual_descriptor[] = {
+	/* model descriptor leaf () */
+	0x00030000,
+	0x00000000,
+	0x00000000,
+	0x4a756a75,		/* J u j u */
+};
+
+static struct fw_descriptor vendor_id_descriptor = {
+	.length = ARRAY_SIZE(vendor_textual_descriptor),
+	.immediate = 0x03d00d1e,
+	.key = 0x81000000,
+	.data = vendor_textual_descriptor,
+};
+
+static struct fw_descriptor model_id_descriptor = {
+	.length = ARRAY_SIZE(model_textual_descriptor),
+	.immediate = 0x17000001,
+	.key = 0x81000000,
+	.data = model_textual_descriptor,
+};
+
+static int __init fw_core_init(void)
+{
+	int retval;
+
+	retval = bus_register(&fw_bus_type);
+	if (retval < 0)
+		return retval;
+
+	fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
+	if (fw_cdev_major < 0) {
+		bus_unregister(&fw_bus_type);
+		return fw_cdev_major;
+	}
+
+	retval = fw_core_add_address_handler(&topology_map,
+					     &topology_map_region);
+	BUG_ON(retval < 0);
+
+	retval = fw_core_add_address_handler(&registers,
+					     &registers_region);
+	BUG_ON(retval < 0);
+
+	/* Add the vendor textual descriptor. */
+	retval = fw_core_add_descriptor(&vendor_id_descriptor);
+	BUG_ON(retval < 0);
+	retval = fw_core_add_descriptor(&model_id_descriptor);
+	BUG_ON(retval < 0);
+
+	return 0;
+}
+
+static void __exit fw_core_cleanup(void)
+{
+	unregister_chrdev(fw_cdev_major, "firewire");
+	bus_unregister(&fw_bus_type);
+}
+
+module_init(fw_core_init);
+module_exit(fw_core_cleanup);
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h
new file mode 100644
index 0000000..acdc3be
--- /dev/null
+++ b/drivers/firewire/fw-transaction.h
@@ -0,0 +1,458 @@
+/*
+ * Copyright (C) 2003-2006 Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __fw_transaction_h
+#define __fw_transaction_h
+
+#include <linux/device.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/dma-mapping.h>
+#include <linux/firewire-constants.h>
+
+#define TCODE_IS_READ_REQUEST(tcode)	(((tcode) & ~1) == 4)
+#define TCODE_IS_BLOCK_PACKET(tcode)	(((tcode) &  1) != 0)
+#define TCODE_IS_REQUEST(tcode)		(((tcode) &  2) == 0)
+#define TCODE_IS_RESPONSE(tcode)	(((tcode) &  2) != 0)
+#define TCODE_HAS_REQUEST_DATA(tcode)	(((tcode) & 12) != 4)
+#define TCODE_HAS_RESPONSE_DATA(tcode)	(((tcode) & 12) != 0)
+
+#define LOCAL_BUS 0xffc0
+
+#define SELFID_PORT_CHILD	0x3
+#define SELFID_PORT_PARENT	0x2
+#define SELFID_PORT_NCONN	0x1
+#define SELFID_PORT_NONE	0x0
+
+#define PHY_PACKET_CONFIG	0x0
+#define PHY_PACKET_LINK_ON	0x1
+#define PHY_PACKET_SELF_ID	0x2
+
+/* Bit fields _within_ the PHY registers. */
+#define PHY_LINK_ACTIVE		0x80
+#define PHY_CONTENDER		0x40
+#define PHY_BUS_RESET		0x40
+#define PHY_BUS_SHORT_RESET	0x40
+
+#define CSR_REGISTER_BASE		0xfffff0000000ULL
+
+/* register offsets relative to CSR_REGISTER_BASE */
+#define CSR_STATE_CLEAR			0x0
+#define CSR_STATE_SET			0x4
+#define CSR_NODE_IDS			0x8
+#define CSR_RESET_START			0xc
+#define CSR_SPLIT_TIMEOUT_HI		0x18
+#define CSR_SPLIT_TIMEOUT_LO		0x1c
+#define CSR_CYCLE_TIME			0x200
+#define CSR_BUS_TIME			0x204
+#define CSR_BUSY_TIMEOUT		0x210
+#define CSR_BUS_MANAGER_ID		0x21c
+#define CSR_BANDWIDTH_AVAILABLE		0x220
+#define CSR_CHANNELS_AVAILABLE		0x224
+#define CSR_CHANNELS_AVAILABLE_HI	0x224
+#define CSR_CHANNELS_AVAILABLE_LO	0x228
+#define CSR_BROADCAST_CHANNEL		0x234
+#define CSR_CONFIG_ROM			0x400
+#define CSR_CONFIG_ROM_END		0x800
+#define CSR_FCP_COMMAND			0xB00
+#define CSR_FCP_RESPONSE		0xD00
+#define CSR_FCP_END			0xF00
+#define CSR_TOPOLOGY_MAP		0x1000
+#define CSR_TOPOLOGY_MAP_END		0x1400
+#define CSR_SPEED_MAP			0x2000
+#define CSR_SPEED_MAP_END		0x3000
+
+#define fw_notify(s, args...) printk(KERN_NOTICE KBUILD_MODNAME ": " s, ## args)
+#define fw_error(s, args...) printk(KERN_ERR KBUILD_MODNAME ": " s, ## args)
+#define fw_debug(s, args...) printk(KERN_DEBUG KBUILD_MODNAME ": " s, ## args)
+
+static inline void
+fw_memcpy_from_be32(void *_dst, void *_src, size_t size)
+{
+	u32 *dst = _dst;
+	u32 *src = _src;
+	int i;
+
+	for (i = 0; i < size / 4; i++)
+		dst[i] = cpu_to_be32(src[i]);
+}
+
+static inline void
+fw_memcpy_to_be32(void *_dst, void *_src, size_t size)
+{
+	fw_memcpy_from_be32(_dst, _src, size);
+}
+
+struct fw_card;
+struct fw_packet;
+struct fw_node;
+struct fw_request;
+
+struct fw_descriptor {
+	struct list_head link;
+	size_t length;
+	u32 immediate;
+	u32 key;
+	const u32 *data;
+};
+
+int fw_core_add_descriptor(struct fw_descriptor *desc);
+void fw_core_remove_descriptor(struct fw_descriptor *desc);
+
+typedef void (*fw_packet_callback_t)(struct fw_packet *packet,
+				     struct fw_card *card, int status);
+
+typedef void (*fw_transaction_callback_t)(struct fw_card *card, int rcode,
+					  void *data,
+					  size_t length,
+					  void *callback_data);
+
+typedef void (*fw_address_callback_t)(struct fw_card *card,
+				      struct fw_request *request,
+				      int tcode, int destination, int source,
+				      int generation, int speed,
+				      unsigned long long offset,
+				      void *data, size_t length,
+				      void *callback_data);
+
+typedef void (*fw_bus_reset_callback_t)(struct fw_card *handle,
+					int node_id, int generation,
+					u32 *self_ids,
+					int self_id_count,
+					void *callback_data);
+
+struct fw_packet {
+	int speed;
+	int generation;
+	u32 header[4];
+	size_t header_length;
+	void *payload;
+	size_t payload_length;
+	u32 timestamp;
+
+	/*
+	 * This callback is called when the packet transmission has
+	 * completed; for successful transmission, the status code is
+	 * the ack received from the destination, otherwise it's a
+	 * negative errno: ENOMEM, ESTALE, ETIMEDOUT, ENODEV, EIO.
+	 * The callback can be called from tasklet context and thus
+	 * must never block.
+	 */
+	fw_packet_callback_t callback;
+	int ack;
+	struct list_head link;
+	void *driver_data;
+};
+
+struct fw_transaction {
+	int node_id; /* The generation is implied; it is always the current. */
+	int tlabel;
+	int timestamp;
+	struct list_head link;
+
+	struct fw_packet packet;
+
+	/*
+	 * The data passed to the callback is valid only during the
+	 * callback.
+	 */
+	fw_transaction_callback_t callback;
+	void *callback_data;
+};
+
+static inline struct fw_packet *
+fw_packet(struct list_head *l)
+{
+	return list_entry(l, struct fw_packet, link);
+}
+
+struct fw_address_handler {
+	u64 offset;
+	size_t length;
+	fw_address_callback_t address_callback;
+	void *callback_data;
+	struct list_head link;
+};
+
+
+struct fw_address_region {
+	u64 start;
+	u64 end;
+};
+
+extern const struct fw_address_region fw_low_memory_region;
+extern const struct fw_address_region fw_high_memory_region;
+extern const struct fw_address_region fw_private_region;
+extern const struct fw_address_region fw_csr_region;
+extern const struct fw_address_region fw_unit_space_region;
+
+int fw_core_add_address_handler(struct fw_address_handler *handler,
+				const struct fw_address_region *region);
+void fw_core_remove_address_handler(struct fw_address_handler *handler);
+void fw_fill_response(struct fw_packet *response, u32 *request_header,
+		      int rcode, void *payload, size_t length);
+void fw_send_response(struct fw_card *card,
+		      struct fw_request *request, int rcode);
+
+extern struct bus_type fw_bus_type;
+
+struct fw_card {
+	const struct fw_card_driver *driver;
+	struct device *device;
+	struct kref kref;
+
+	int node_id;
+	int generation;
+	/* This is the generation used for timestamping incoming requests. */
+	int request_generation;
+	int current_tlabel, tlabel_mask;
+	struct list_head transaction_list;
+	struct timer_list flush_timer;
+	unsigned long reset_jiffies;
+
+	unsigned long long guid;
+	int max_receive;
+	int link_speed;
+	int config_rom_generation;
+
+	/*
+	 * We need to store up to 4 self ID for a maximum of 63
+	 * devices plus 3 words for the topology map header.
+	 */
+	int self_id_count;
+	u32 topology_map[252 + 3];
+
+	spinlock_t lock; /* Take this lock when handling the lists in
+			  * this struct. */
+	struct fw_node *local_node;
+	struct fw_node *root_node;
+	struct fw_node *irm_node;
+	int color;
+	int gap_count;
+	int topology_type;
+
+	int index;
+
+	struct list_head link;
+
+	/* Work struct for BM duties. */
+	struct delayed_work work;
+	int bm_retries;
+	int bm_generation;
+};
+
+struct fw_card *fw_card_get(struct fw_card *card);
+void fw_card_put(struct fw_card *card);
+
+/*
+ * The iso packet format allows for an immediate header/payload part
+ * stored in 'header' immediately after the packet info plus an
+ * indirect payload part that is pointer to by the 'payload' field.
+ * Applications can use one or the other or both to implement simple
+ * low-bandwidth streaming (e.g. audio) or more advanced
+ * scatter-gather streaming (e.g. assembling video frame automatically).
+ */
+
+struct fw_iso_packet {
+	u16 payload_length;	/* Length of indirect payload. */
+	u32 interrupt : 1;	/* Generate interrupt on this packet */
+	u32 skip : 1;		/* Set to not send packet at all. */
+	u32 tag : 2;
+	u32 sy : 4;
+	u32 header_length : 8;	/* Length of immediate header. */
+	u32 header[0];
+};
+
+#define FW_ISO_CONTEXT_TRANSMIT	0
+#define FW_ISO_CONTEXT_RECEIVE	1
+
+#define FW_ISO_CONTEXT_MATCH_TAG0	 1
+#define FW_ISO_CONTEXT_MATCH_TAG1	 2
+#define FW_ISO_CONTEXT_MATCH_TAG2	 4
+#define FW_ISO_CONTEXT_MATCH_TAG3	 8
+#define FW_ISO_CONTEXT_MATCH_ALL_TAGS	15
+
+struct fw_iso_context;
+
+typedef void (*fw_iso_callback_t)(struct fw_iso_context *context,
+				  u32 cycle,
+				  size_t header_length,
+				  void *header,
+				  void *data);
+
+/*
+ * An iso buffer is just a set of pages mapped for DMA in the
+ * specified direction.  Since the pages are to be used for DMA, they
+ * are not mapped into the kernel virtual address space.  We store the
+ * DMA address in the page private. The helper function
+ * fw_iso_buffer_map() will map the pages into a given vma.
+ */
+
+struct fw_iso_buffer {
+	enum dma_data_direction direction;
+	struct page **pages;
+	int page_count;
+};
+
+struct fw_iso_context {
+	struct fw_card *card;
+	int type;
+	int channel;
+	int speed;
+	size_t header_size;
+	fw_iso_callback_t callback;
+	void *callback_data;
+};
+
+int
+fw_iso_buffer_init(struct fw_iso_buffer *buffer,
+		   struct fw_card *card,
+		   int page_count,
+		   enum dma_data_direction direction);
+int
+fw_iso_buffer_map(struct fw_iso_buffer *buffer, struct vm_area_struct *vma);
+void
+fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card);
+
+struct fw_iso_context *
+fw_iso_context_create(struct fw_card *card, int type,
+		      int channel, int speed, size_t header_size,
+		      fw_iso_callback_t callback, void *callback_data);
+
+void
+fw_iso_context_destroy(struct fw_iso_context *ctx);
+
+int
+fw_iso_context_queue(struct fw_iso_context *ctx,
+		     struct fw_iso_packet *packet,
+		     struct fw_iso_buffer *buffer,
+		     unsigned long payload);
+
+int
+fw_iso_context_start(struct fw_iso_context *ctx,
+		     int cycle, int sync, int tags);
+
+int
+fw_iso_context_stop(struct fw_iso_context *ctx);
+
+struct fw_card_driver {
+	const char *name;
+
+	/*
+	 * Enable the given card with the given initial config rom.
+	 * This function is expected to activate the card, and either
+	 * enable the PHY or set the link_on bit and initiate a bus
+	 * reset.
+	 */
+	int (*enable)(struct fw_card *card, u32 *config_rom, size_t length);
+
+	int (*update_phy_reg)(struct fw_card *card, int address,
+			      int clear_bits, int set_bits);
+
+	/*
+	 * Update the config rom for an enabled card.  This function
+	 * should change the config rom that is presented on the bus
+	 * an initiate a bus reset.
+	 */
+	int (*set_config_rom)(struct fw_card *card,
+			      u32 *config_rom, size_t length);
+
+	void (*send_request)(struct fw_card *card, struct fw_packet *packet);
+	void (*send_response)(struct fw_card *card, struct fw_packet *packet);
+	/* Calling cancel is valid once a packet has been submitted. */
+	int (*cancel_packet)(struct fw_card *card, struct fw_packet *packet);
+
+	/*
+	 * Allow the specified node ID to do direct DMA out and in of
+	 * host memory.  The card will disable this for all node when
+	 * a bus reset happens, so driver need to reenable this after
+	 * bus reset.  Returns 0 on success, -ENODEV if the card
+	 * doesn't support this, -ESTALE if the generation doesn't
+	 * match.
+	 */
+	int (*enable_phys_dma)(struct fw_card *card,
+			       int node_id, int generation);
+
+	u64 (*get_bus_time)(struct fw_card *card);
+
+	struct fw_iso_context *
+	(*allocate_iso_context)(struct fw_card *card,
+				int type, size_t header_size);
+	void (*free_iso_context)(struct fw_iso_context *ctx);
+
+	int (*start_iso)(struct fw_iso_context *ctx,
+			 s32 cycle, u32 sync, u32 tags);
+
+	int (*queue_iso)(struct fw_iso_context *ctx,
+			 struct fw_iso_packet *packet,
+			 struct fw_iso_buffer *buffer,
+			 unsigned long payload);
+
+	int (*stop_iso)(struct fw_iso_context *ctx);
+};
+
+int
+fw_core_initiate_bus_reset(struct fw_card *card, int short_reset);
+
+void
+fw_send_request(struct fw_card *card, struct fw_transaction *t,
+		int tcode, int node_id, int generation, int speed,
+		unsigned long long offset,
+		void *data, size_t length,
+		fw_transaction_callback_t callback, void *callback_data);
+
+int fw_cancel_transaction(struct fw_card *card,
+			  struct fw_transaction *transaction);
+
+void fw_flush_transactions(struct fw_card *card);
+
+void fw_send_phy_config(struct fw_card *card,
+			int node_id, int generation, int gap_count);
+
+/*
+ * Called by the topology code to inform the device code of node
+ * activity; found, lost, or updated nodes.
+ */
+void
+fw_node_event(struct fw_card *card, struct fw_node *node, int event);
+
+/* API used by card level drivers */
+
+void
+fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver,
+		   struct device *device);
+int
+fw_card_add(struct fw_card *card,
+	    u32 max_receive, u32 link_speed, u64 guid);
+
+void
+fw_core_remove_card(struct fw_card *card);
+
+void
+fw_core_handle_bus_reset(struct fw_card *card,
+			 int node_id, int generation,
+			 int self_id_count, u32 *self_ids);
+void
+fw_core_handle_request(struct fw_card *card, struct fw_packet *request);
+
+void
+fw_core_handle_response(struct fw_card *card, struct fw_packet *packet);
+
+#endif /* __fw_transaction_h */
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index a19b65e..7f81789 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -240,11 +240,94 @@
 }
 #endif
 
+static inline int match_scancode(int code, int scancode)
+{
+	if (scancode == 0)
+		return 1;
+	return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode);
+}
+
+static inline int match_keycode(int code, int keycode)
+{
+	if (keycode == 0)
+		return 1;
+	return (code == keycode);
+}
+
+static struct hid_usage *hidinput_find_key(struct hid_device *hid,
+		int scancode, int keycode)
+{
+	int i, j, k;
+	struct hid_report *report;
+	struct hid_usage *usage;
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
+		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
+			for (i = 0; i < report->maxfield; i++) {
+				for ( j = 0; j < report->field[i]->maxusage; j++) {
+					usage = report->field[i]->usage + j;
+					if (usage->type == EV_KEY &&
+						match_scancode(usage->hid, scancode) &&
+						match_keycode(usage->code, keycode))
+						return usage;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+
+static int hidinput_getkeycode(struct input_dev *dev, int scancode,
+				int *keycode)
+{
+	struct hid_device *hid = dev->private;
+	struct hid_usage *usage;
+	
+	usage = hidinput_find_key(hid, scancode, 0);
+	if (usage) {
+		*keycode = usage->code;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int hidinput_setkeycode(struct input_dev *dev, int scancode,
+				int keycode)
+{
+	struct hid_device *hid = dev->private;
+	struct hid_usage *usage;
+	int old_keycode;
+	
+	if (keycode < 0 || keycode > KEY_MAX)
+		return -EINVAL;
+	
+	usage = hidinput_find_key(hid, scancode, 0);
+	if (usage) {
+		old_keycode = usage->code;
+		usage->code = keycode;
+		
+		clear_bit(old_keycode, dev->keybit);
+		set_bit(usage->code, dev->keybit);
+#ifdef CONFIG_HID_DEBUG
+		printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
+#endif
+		/* Set the keybit for the old keycode if the old keycode is used
+		 * by another key */
+		if (hidinput_find_key (hid, 0, old_keycode))
+			set_bit(old_keycode, dev->keybit);
+		
+		return 0;
+	}
+	
+	return -EINVAL;
+}
+
+
 static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
 				     struct hid_usage *usage)
 {
 	struct input_dev *input = hidinput->input;
-	struct hid_device *device = input->private;
+	struct hid_device *device = input_get_drvdata(input);
 	int max = 0, code;
 	unsigned long *bit = NULL;
 
@@ -553,6 +636,7 @@
 				case 0x1015: map_key_clear(KEY_RECORD);		break;
 				case 0x1016: map_key_clear(KEY_PLAYER);		break;
 				case 0x1017: map_key_clear(KEY_EJECTCD);	break;
+				case 0x1018: map_key_clear(KEY_MEDIA);          break;
 				case 0x1019: map_key_clear(KEY_PROG1);		break;
 				case 0x101a: map_key_clear(KEY_PROG2);		break;
 				case 0x101b: map_key_clear(KEY_PROG3);		break;
@@ -560,9 +644,12 @@
 				case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
 				case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
 				case 0x1023: map_key_clear(KEY_CLOSE);		break;
+				case 0x1027: map_key_clear(KEY_MENU);           break;
 				/* this one is marked as 'Rotate' */
 				case 0x1028: map_key_clear(KEY_ANGLE);		break;
 				case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
+				case 0x102a: map_key_clear(KEY_BACK);           break;
+				case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);   break;
 				case 0x1041: map_key_clear(KEY_BATTERY);	break;
 				case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
 				case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
@@ -855,13 +942,15 @@
 
 static int hidinput_open(struct input_dev *dev)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
+
 	return hid->hid_open(hid);
 }
 
 static void hidinput_close(struct input_dev *dev)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
+
 	hid->hid_close(hid);
 }
 
@@ -909,10 +998,12 @@
 					return -1;
 				}
 
-				input_dev->private = hid;
+				input_set_drvdata(input_dev, hid);
 				input_dev->event = hid->hidinput_input_event;
 				input_dev->open = hidinput_open;
 				input_dev->close = hidinput_close;
+				input_dev->setkeycode = hidinput_setkeycode;
+				input_dev->getkeycode = hidinput_getkeycode;
 
 				input_dev->name = hid->name;
 				input_dev->phys = hid->phys;
@@ -921,7 +1012,7 @@
 				input_dev->id.vendor  = hid->vendor;
 				input_dev->id.product = hid->product;
 				input_dev->id.version = hid->version;
-				input_dev->cdev.dev = hid->dev;
+				input_dev->dev.parent = hid->dev;
 				hidinput->input = input_dev;
 				list_add_tail(&hidinput->list, &hid->inputs);
 			}
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 7c87bdc..1b4b572 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -25,12 +25,12 @@
 	depends on USB_HID && INPUT=n
 
 config USB_HIDINPUT_POWERBOOK
-	bool "Enable support for iBook/PowerBook special keys"
+	bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
 	default n
 	depends on USB_HID
 	help
 	  Say Y here if you want support for the special keys (Fn, Numlock) on
-	  Apple iBooks and PowerBooks.
+	  Apple iBooks, PowerBooks, MacBooks and MacBook Pros.
 
 	  If unsure, say N.
 
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 91d6103..d91b9da 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -446,7 +446,7 @@
 
 static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
 	struct hid_field *field;
 	int offset;
 
@@ -626,14 +626,10 @@
 {
 	struct usbhid_device *usbhid = hid->driver_data;
 
-	if (usbhid->inbuf)
-		usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
-	if (usbhid->outbuf)
-		usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
-	if (usbhid->cr)
-		usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
-	if (usbhid->ctrlbuf)
-		usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
+	usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+	usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+	usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
+	usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
 }
 
 /*
@@ -692,6 +688,30 @@
 	}
 }
 
+/*
+ * Some USB barcode readers from cypress have usage min and usage max in
+ * the wrong order
+ */
+static void hid_fixup_cypress_descriptor(unsigned char *rdesc, int rsize)
+{
+	short fixed = 0;
+	int i;
+
+	for (i = 0; i < rsize - 4; i++) {
+		if (rdesc[i] == 0x29 && rdesc [i+2] == 0x19) {
+			unsigned char tmp;
+
+			rdesc[i] = 0x19; rdesc[i+2] = 0x29;
+			tmp = rdesc[i+3];
+			rdesc[i+3] = rdesc[i+1];
+			rdesc[i+1] = tmp;
+		}
+	}
+
+	if (fixed)
+		info("Fixing up Cypress report descriptor");
+}
+
 static struct hid_device *usb_hid_configure(struct usb_interface *intf)
 {
 	struct usb_host_interface *interface = intf->cur_altsetting;
@@ -758,6 +778,9 @@
 	if (quirks & HID_QUIRK_LOGITECH_DESCRIPTOR)
 		hid_fixup_logitech_descriptor(rdesc, rsize);
 
+	if (quirks & HID_QUIRK_SWAPPED_MIN_MAX)
+		hid_fixup_cypress_descriptor(rdesc, rsize);
+
 #ifdef CONFIG_HID_DEBUG
 	printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n);
 	for (n = 0; n < rsize; n++)
diff --git a/drivers/hid/usbhid/hid-lgff.c b/drivers/hid/usbhid/hid-lgff.c
index 92d2553..c5cd410 100644
--- a/drivers/hid/usbhid/hid-lgff.c
+++ b/drivers/hid/usbhid/hid-lgff.c
@@ -60,7 +60,7 @@
 
 static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
 	struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
 	struct hid_report *report = list_entry(report_list->next, struct hid_report, list);
 	int x, y;
diff --git a/drivers/hid/usbhid/hid-plff.c b/drivers/hid/usbhid/hid-plff.c
index 76d2e6e..d6a8f2b 100644
--- a/drivers/hid/usbhid/hid-plff.c
+++ b/drivers/hid/usbhid/hid-plff.c
@@ -37,7 +37,7 @@
 static int hid_plff_play(struct input_dev *dev, void *data,
 			 struct ff_effect *effect)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
 	struct plff_device *plff = data;
 	int left, right;
 
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 17a8755..f6c4145 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -92,6 +92,8 @@
 #define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
 #define USB_DEVICE_ID_CYPRESS_HIDCOM	0x5500
 #define USB_DEVICE_ID_CYPRESS_ULTRAMOUSE	0x7417
+#define USB_DEVICE_ID_CYPRESS_BARCODE_1	0xde61
+#define USB_DEVICE_ID_CYPRESS_BARCODE_2	0xde64
 
 #define USB_VENDOR_ID_DELL		0x413c
 #define USB_DEVICE_ID_DELL_W7658	0x2005
@@ -193,6 +195,7 @@
 
 #define USB_VENDOR_ID_LOGITECH		0x046d
 #define USB_DEVICE_ID_LOGITECH_RECEIVER	0xc101
+#define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
 #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
 #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
 #define USB_DEVICE_ID_MX3000_RECEIVER	0xc513
@@ -422,6 +425,7 @@
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
@@ -445,6 +449,9 @@
 
 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
 
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_SWAPPED_MIN_MAX },
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_SWAPPED_MIN_MAX },
+
 	{ 0, 0 }
 };
 
diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
index ab67331..ab5ba6e 100644
--- a/drivers/hid/usbhid/hid-tmff.c
+++ b/drivers/hid/usbhid/hid-tmff.c
@@ -59,7 +59,7 @@
 
 static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *effect)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
 	struct tmff_device *tmff = data;
 	int left, right;	/* Rumbling */
 
diff --git a/drivers/hid/usbhid/hid-zpff.c b/drivers/hid/usbhid/hid-zpff.c
index 7bd8238..a7fbffc 100644
--- a/drivers/hid/usbhid/hid-zpff.c
+++ b/drivers/hid/usbhid/hid-zpff.c
@@ -37,7 +37,7 @@
 static int hid_zpff_play(struct input_dev *dev, void *data,
 			 struct ff_effect *effect)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
 	struct zpff_device *zpff = data;
 	int left, right;
 
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index a8b3d66..488d61b 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -51,6 +51,7 @@
 	wait_queue_head_t wait;
 	struct hid_device *hid;
 	struct list_head list;
+	spinlock_t list_lock;
 };
 
 struct hiddev_list {
@@ -161,7 +162,9 @@
 {
 	struct hiddev *hiddev = hid->hiddev;
 	struct hiddev_list *list;
+	unsigned long flags;
 
+	spin_lock_irqsave(&hiddev->list_lock, flags);
 	list_for_each_entry(list, &hiddev->list, node) {
 		if (uref->field_index != HID_FIELD_INDEX_NONE ||
 		    (list->flags & HIDDEV_FLAG_REPORT) != 0) {
@@ -171,6 +174,7 @@
 			kill_fasync(&list->fasync, SIGIO, POLL_IN);
 		}
 	}
+	spin_unlock_irqrestore(&hiddev->list_lock, flags);
 
 	wake_up_interruptible(&hiddev->wait);
 }
@@ -235,9 +239,13 @@
 static int hiddev_release(struct inode * inode, struct file * file)
 {
 	struct hiddev_list *list = file->private_data;
+	unsigned long flags;
 
 	hiddev_fasync(-1, file, 0);
+
+	spin_lock_irqsave(&list->hiddev->list_lock, flags);
 	list_del(&list->node);
+	spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
 
 	if (!--list->hiddev->open) {
 		if (list->hiddev->exist)
@@ -257,6 +265,7 @@
 static int hiddev_open(struct inode *inode, struct file *file)
 {
 	struct hiddev_list *list;
+	unsigned long flags;
 
 	int i = iminor(inode) - HIDDEV_MINOR_BASE;
 
@@ -267,7 +276,11 @@
 		return -ENOMEM;
 
 	list->hiddev = hiddev_table[i];
+
+	spin_lock_irqsave(&list->hiddev->list_lock, flags);
 	list_add_tail(&list->node, &hiddev_table[i]->list);
+	spin_unlock_irqrestore(&list->hiddev->list_lock, flags);
+
 	file->private_data = list;
 
 	if (!list->hiddev->open++)
@@ -773,6 +786,7 @@
 
 	init_waitqueue_head(&hiddev->wait);
 	INIT_LIST_HEAD(&hiddev->list);
+	spin_lock_init(&hiddev->list_lock);
 	hiddev->hid = hid;
 	hiddev->exist = 1;
 
diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
index 65aa12e8..1309787 100644
--- a/drivers/hid/usbhid/usbkbd.c
+++ b/drivers/hid/usbhid/usbkbd.c
@@ -133,12 +133,11 @@
 static int usb_kbd_event(struct input_dev *dev, unsigned int type,
 			 unsigned int code, int value)
 {
-	struct usb_kbd *kbd = dev->private;
+	struct usb_kbd *kbd = input_get_drvdata(dev);
 
 	if (type != EV_LED)
 		return -1;
 
-
 	kbd->newleds = (!!test_bit(LED_KANA,    dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
 		       (!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL,   dev->led) << 1) |
 		       (!!test_bit(LED_NUML,    dev->led));
@@ -175,7 +174,7 @@
 
 static int usb_kbd_open(struct input_dev *dev)
 {
-	struct usb_kbd *kbd = dev->private;
+	struct usb_kbd *kbd = input_get_drvdata(dev);
 
 	kbd->irq->dev = kbd->usbdev;
 	if (usb_submit_urb(kbd->irq, GFP_KERNEL))
@@ -186,7 +185,7 @@
 
 static void usb_kbd_close(struct input_dev *dev)
 {
-	struct usb_kbd *kbd = dev->private;
+	struct usb_kbd *kbd = input_get_drvdata(dev);
 
 	usb_kill_urb(kbd->irq);
 }
@@ -211,12 +210,9 @@
 {
 	usb_free_urb(kbd->irq);
 	usb_free_urb(kbd->led);
-	if (kbd->new)
-		usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
-	if (kbd->cr)
-		usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
-	if (kbd->leds)
-		usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
+	usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
+	usb_buffer_free(dev, sizeof(struct usb_ctrlrequest), kbd->cr, kbd->cr_dma);
+	usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma);
 }
 
 static int usb_kbd_probe(struct usb_interface *iface,
@@ -274,8 +270,9 @@
 	input_dev->name = kbd->name;
 	input_dev->phys = kbd->phys;
 	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &iface->dev;
-	input_dev->private = kbd;
+	input_dev->dev.parent = &iface->dev;
+
+	input_set_drvdata(input_dev, kbd);
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
 	input_dev->ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
index 573776d..5345c73 100644
--- a/drivers/hid/usbhid/usbmouse.c
+++ b/drivers/hid/usbhid/usbmouse.c
@@ -96,7 +96,7 @@
 
 static int usb_mouse_open(struct input_dev *dev)
 {
-	struct usb_mouse *mouse = dev->private;
+	struct usb_mouse *mouse = input_get_drvdata(dev);
 
 	mouse->irq->dev = mouse->usbdev;
 	if (usb_submit_urb(mouse->irq, GFP_KERNEL))
@@ -107,7 +107,7 @@
 
 static void usb_mouse_close(struct input_dev *dev)
 {
-	struct usb_mouse *mouse = dev->private;
+	struct usb_mouse *mouse = input_get_drvdata(dev);
 
 	usb_kill_urb(mouse->irq);
 }
@@ -171,7 +171,7 @@
 	input_dev->name = mouse->name;
 	input_dev->phys = mouse->phys;
 	usb_to_input_id(dev, &input_dev->id);
-	input_dev->cdev.dev = &intf->dev;
+	input_dev->dev.parent = &intf->dev;
 
 	input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
@@ -179,7 +179,8 @@
 	input_dev->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
 	input_dev->relbit[0] |= BIT(REL_WHEEL);
 
-	input_dev->private = mouse;
+	input_set_drvdata(input_dev, mouse);
+
 	input_dev->open = usb_mouse_open;
 	input_dev->close = usb_mouse_close;
 
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 3ba3a52..4d1cb5b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -4,6 +4,7 @@
 
 menuconfig HWMON
 	tristate "Hardware Monitoring support"
+	depends on HAS_IOMEM
 	default y
 	help
 	  Hardware monitoring devices let you monitor the hardware health
diff --git a/drivers/hwmon/ams/ams-input.c b/drivers/hwmon/ams/ams-input.c
index 1821016..ca7095d 100644
--- a/drivers/hwmon/ams/ams-input.c
+++ b/drivers/hwmon/ams/ams-input.c
@@ -87,7 +87,7 @@
 	ams_info.idev->id.vendor = 0;
 	ams_info.idev->open = ams_input_open;
 	ams_info.idev->close = ams_input_close;
-	ams_info.idev->cdev.dev = &ams_info.of_dev->dev;
+	ams_info.idev->dev.parent = &ams_info.of_dev->dev;
 
 	input_set_abs_params(ams_info.idev, ABS_X, -50, 50, 3, 0);
 	input_set_abs_params(ams_info.idev, ABS_Y, -50, 50, 3, 0);
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index b51c104..0c160675 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -1100,7 +1100,7 @@
 	/* initialize the input class */
 	applesmc_idev->name = "applesmc";
 	applesmc_idev->id.bustype = BUS_HOST;
-	applesmc_idev->cdev.dev = &pdev->dev;
+	applesmc_idev->dev.parent = &pdev->dev;
 	applesmc_idev->evbit[0] = BIT(EV_ABS);
 	applesmc_idev->open = applesmc_idev_open;
 	applesmc_idev->close = applesmc_idev_close;
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index f82fa2d..e0cf5e6 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -574,7 +574,7 @@
 
 	/* initialize the input class */
 	hdaps_idev->name = "hdaps";
-	hdaps_idev->cdev.dev = &pdev->dev;
+	hdaps_idev->dev.parent = &pdev->dev;
 	hdaps_idev->evbit[0] = BIT(EV_ABS);
 	input_set_abs_params(hdaps_idev, ABS_X,
 			-256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 434a61b..9686734 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -4,6 +4,7 @@
 
 menuconfig I2C
 	tristate "I2C support"
+	depends on HAS_IOMEM
 	---help---
 	  I2C (pronounce: I-square-C) is a slow serial bus protocol used in
 	  many micro controller applications and developed by Philips.  SMBus,
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index f35156c..9c8b6d5 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/delay.h>
@@ -226,13 +227,14 @@
 	adapter->algo = &at91_algorithm;
 	adapter->class = I2C_CLASS_HWMON;
 	adapter->dev.parent = &pdev->dev;
+	/* adapter->id == 0 ... only one TWI controller for now */
 
 	platform_set_drvdata(pdev, adapter);
 
 	clk_enable(twi_clk);		/* enable peripheral clock */
 	at91_twi_hwinit();		/* initialize TWI controller */
 
-	rc = i2c_add_adapter(adapter);
+	rc = i2c_add_numbered_adapter(adapter);
 	if (rc) {
 		dev_err(&pdev->dev, "Adapter %s registration failed\n",
 				adapter->name);
@@ -295,6 +297,9 @@
 #define at91_i2c_resume		NULL
 #endif
 
+/* work with "modprobe at91_i2c" from hotplugging or coldplugging */
+MODULE_ALIAS("at91_i2c");
+
 static struct platform_driver at91_i2c_driver = {
 	.probe		= at91_i2c_probe,
 	.remove		= __devexit_p(at91_i2c_remove),
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
index 873544a..8a0a99b 100644
--- a/drivers/i2c/busses/i2c-pxa.c
+++ b/drivers/i2c/busses/i2c-pxa.c
@@ -548,7 +548,7 @@
 	 */
 	icr = readl(_ICR(i2c));
 	icr &= ~(ICR_STOP | ICR_ACKNAK);
-	writel(icr, _IRC(i2c));
+	writel(icr, _ICR(i2c));
 }
 
 /*
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 1d06b41..9040809 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -7,6 +7,7 @@
 if BLOCK
 
 menu "ATA/ATAPI/MFM/RLL support"
+	depends on HAS_IOMEM
 
 config IDE
 	tristate "ATA/ATAPI/MFM/RLL support"
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 61d7809..8012b3b 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -1,4 +1,7 @@
 menu "IEEE 1394 (FireWire) support"
+	depends on PCI || BROKEN
+
+source "drivers/firewire/Kconfig"
 
 config IEEE1394
 	tristate "IEEE 1394 (FireWire) support"
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index 37deaae..994decc 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -1,4 +1,5 @@
 menu "InfiniBand support"
+	depends on HAS_IOMEM
 
 config INFINIBAND
 	depends on PCI || BROKEN
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index 0e9b695..f814fb3 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Input device support"
+	depends on !S390
 
 config INPUT
 	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 55a7259..b234729 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -336,7 +336,7 @@
 
 	if (compat) {
 		len = NBITS_COMPAT(maxbit) * sizeof(compat_long_t);
-		if (len < maxlen)
+		if (len > maxlen)
 			len = maxlen;
 
 		for (i = 0; i < len / sizeof(compat_long_t); i++)
diff --git a/drivers/input/misc/ixp4xx-beeper.c b/drivers/input/misc/ixp4xx-beeper.c
index 3d4b619..e759944 100644
--- a/drivers/input/misc/ixp4xx-beeper.c
+++ b/drivers/input/misc/ixp4xx-beeper.c
@@ -51,7 +51,7 @@
 
 static int ixp4xx_spkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
+	unsigned int pin = (unsigned int) input_get_drvdata(dev);
 	unsigned int count = 0;
 
 	if (type != EV_SND)
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index c90afee..d42fe89cd 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "ISDN subsystem"
+	depends on !S390
 
 config ISDN
 	tristate "ISDN support"
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
index 703cc88..e8e37d8 100644
--- a/drivers/kvm/Kconfig
+++ b/drivers/kvm/Kconfig
@@ -2,6 +2,7 @@
 # KVM configuration
 #
 menu "Virtualization"
+	depends on X86
 
 config KVM
 	tristate "Kernel-based Virtual Machine (KVM) support"
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 80acd08..87d2046 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -1,5 +1,6 @@
 
 menu "LED devices"
+	depends on HAS_IOMEM
 
 config NEW_LEDS
 	bool "LED Support"
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 65814b0..c10ce91 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5103,7 +5103,7 @@
 		 *
 		 * Note: the following is an unsigned comparison.
 		 */
-		if ((curr_events - rdev->last_events + 4096) > 8192) {
+		if ((long)curr_events - (long)rdev->last_events > 4096) {
 			rdev->last_events = curr_events;
 			idle = 0;
 		}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 97ee870..3a95cc5 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -271,21 +271,25 @@
 	 */
 	update_head_pos(mirror, r1_bio);
 
-	if (uptodate || (conf->raid_disks - conf->mddev->degraded) <= 1) {
-		/*
-		 * Set R1BIO_Uptodate in our master bio, so that
-		 * we will return a good error code for to the higher
-		 * levels even if IO on some other mirrored buffer fails.
-		 *
-		 * The 'master' represents the composite IO operation to
-		 * user-side. So if something waits for IO, then it will
-		 * wait for the 'master' bio.
+	if (uptodate)
+		set_bit(R1BIO_Uptodate, &r1_bio->state);
+	else {
+		/* If all other devices have failed, we want to return
+		 * the error upwards rather than fail the last device.
+		 * Here we redefine "uptodate" to mean "Don't want to retry"
 		 */
-		if (uptodate)
-			set_bit(R1BIO_Uptodate, &r1_bio->state);
+		unsigned long flags;
+		spin_lock_irqsave(&conf->device_lock, flags);
+		if (r1_bio->mddev->degraded == conf->raid_disks ||
+		    (r1_bio->mddev->degraded == conf->raid_disks-1 &&
+		     !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags)))
+			uptodate = 1;
+		spin_unlock_irqrestore(&conf->device_lock, flags);
+	}
 
+	if (uptodate)
 		raid_end_bio_io(r1_bio);
-	} else {
+	else {
 		/*
 		 * oops, read error:
 		 */
@@ -992,13 +996,14 @@
 		unsigned long flags;
 		spin_lock_irqsave(&conf->device_lock, flags);
 		mddev->degraded++;
+		set_bit(Faulty, &rdev->flags);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 		/*
 		 * if recovery is running, make sure it aborts.
 		 */
 		set_bit(MD_RECOVERY_ERR, &mddev->recovery);
-	}
-	set_bit(Faulty, &rdev->flags);
+	} else
+		set_bit(Faulty, &rdev->flags);
 	set_bit(MD_CHANGE_DEVS, &mddev->flags);
 	printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n"
 		"	Operation continuing on %d devices\n",
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 91d25798..3a80e0c 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Multimedia devices"
+	depends on HAS_IOMEM
 
 config VIDEO_DEV
 	tristate "Video For Linux"
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 71037f9..c88cc75 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -1,5 +1,6 @@
 
 menu "Fusion MPT device support"
+	depends on PCI
 
 config FUSION
 	bool
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 6443392..f4ac21e 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -1,5 +1,6 @@
 
 menu "I2O device support"
+	depends on PCI
 
 config I2O
 	tristate "I2O support"
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index ab6e985..a20a51e 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Multifunction device drivers"
+	depends on HAS_IOMEM
 
 config MFD_SM501
 	tristate "Support for Silicon Motion SM501"
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 877e790..2f2fbff 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -130,7 +130,7 @@
 
 	  Read <file:Documentation/sony-laptop.txt> for more information.
 
-config SONY_LAPTOP_OLD
+config SONYPI_COMPAT
 	bool "Sonypi compatibility"
 	depends on SONY_LAPTOP
 	  ---help---
diff --git a/drivers/misc/asus-laptop.c b/drivers/misc/asus-laptop.c
index 65c32a9..4f9060a 100644
--- a/drivers/misc/asus-laptop.c
+++ b/drivers/misc/asus-laptop.c
@@ -30,7 +30,7 @@
  *  Eric Burghard  - LED display support for W1N
  *  Josh Green     - Light Sens support
  *  Thomas Tuttle  - His first patch for led support was very helpfull
- *
+ *  Sam Lin        - GPS support
  */
 
 #include <linux/autoconf.h>
@@ -48,7 +48,7 @@
 #include <acpi/acpi_bus.h>
 #include <asm/uaccess.h>
 
-#define ASUS_LAPTOP_VERSION "0.41"
+#define ASUS_LAPTOP_VERSION "0.42"
 
 #define ASUS_HOTK_NAME          "Asus Laptop Support"
 #define ASUS_HOTK_CLASS         "hotkey"
@@ -83,6 +83,7 @@
 #define PLED_ON     0x20	//Phone LED
 #define GLED_ON     0x40	//Gaming LED
 #define LCD_ON      0x80	//LCD backlight
+#define GPS_ON      0x100	//GPS
 
 #define ASUS_LOG    ASUS_HOTK_FILE ": "
 #define ASUS_ERR    KERN_ERR    ASUS_LOG
@@ -148,7 +149,7 @@
 ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD",	/*  A6B, A6K A6R A7D F3JM L4R M6R A3G
 							   M6A M6V VX-1 V6J V6V W3Z */
 	    "\\_SB.PCI0.P0P2.VGA.GETD",	/* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V
-					   S5A M5A z33A W1Jc W2V */
+					   S5A M5A z33A W1Jc W2V G1 */
 	    "\\_SB.PCI0.P0P3.VGA.GETD",	/* A6V A6Q */
 	    "\\_SB.PCI0.P0PA.VGA.GETD",	/* A6T, A6M */
 	    "\\_SB.PCI0.PCI1.VGAC.NMAP",	/* L3C */
@@ -162,6 +163,12 @@
 ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC");	/* Z71A Z71V */
 ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL");	/* Z71A Z71V */
 
+/* GPS */
+/* R2H use different handle for GPS on/off */
+ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON");	/* R2H */
+ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF");	/* R2H */
+ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST");
+
 /*
  * This is the main structure, we can use it to store anything interesting
  * about the hotk device
@@ -278,12 +285,28 @@
 	return (hotk->status & mask) ? 1 : 0;
 }
 
+static int read_gps_status(void)
+{
+	ulong status;
+	acpi_status rv = AE_OK;
+
+	rv = acpi_evaluate_integer(gps_status_handle, NULL, NULL, &status);
+	if (ACPI_FAILURE(rv))
+		printk(ASUS_WARNING "Error reading GPS status\n");
+	else
+		return status ? 1 : 0;
+
+	return (hotk->status & GPS_ON) ? 1 : 0;
+}
+
 /* Generic LED functions */
 static int read_status(int mask)
 {
 	/* There is a special method for both wireless devices */
 	if (mask == BT_ON || mask == WL_ON)
 		return read_wireless_status(mask);
+	else if (mask == GPS_ON)
+		return read_gps_status();
 
 	return (hotk->status & mask) ? 1 : 0;
 }
@@ -299,6 +322,10 @@
 	case GLED_ON:
 		out = (out & 0x1) + 1;
 		break;
+	case GPS_ON:
+		handle = (out) ? gps_on_handle : gps_off_handle;
+		out = 0x02;
+		break;
 	default:
 		out &= 0x1;
 		break;
@@ -667,6 +694,21 @@
 	return rv;
 }
 
+/*
+ * GPS
+ */
+static ssize_t show_gps(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", read_status(GPS_ON));
+}
+
+static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	return store_status(buf, count, NULL, GPS_ON);
+}
+
 static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
 {
 	/* TODO Find a better way to handle events count. */
@@ -715,6 +757,7 @@
 static ASUS_CREATE_DEVICE_ATTR(ledd);
 static ASUS_CREATE_DEVICE_ATTR(ls_switch);
 static ASUS_CREATE_DEVICE_ATTR(ls_level);
+static ASUS_CREATE_DEVICE_ATTR(gps);
 
 static struct attribute *asuspf_attributes[] = {
 	&dev_attr_infos.attr,
@@ -724,6 +767,7 @@
 	&dev_attr_ledd.attr,
 	&dev_attr_ls_switch.attr,
 	&dev_attr_ls_level.attr,
+	&dev_attr_gps.attr,
 	NULL
 };
 
@@ -763,6 +807,9 @@
 		ASUS_SET_DEVICE_ATTR(ls_level, 0644, show_lslvl, store_lslvl);
 		ASUS_SET_DEVICE_ATTR(ls_switch, 0644, show_lssw, store_lssw);
 	}
+
+	if (gps_status_handle && gps_on_handle && gps_off_handle)
+		ASUS_SET_DEVICE_ATTR(gps, 0644, show_gps, store_gps);
 }
 
 static int asus_handle_init(char *name, acpi_handle * handle,
@@ -890,9 +937,13 @@
 
 	/* There is a lot of models with "ALSL", but a few get
 	   a real light sens, so we need to check it. */
-	if (ASUS_HANDLE_INIT(ls_switch))
+	if (!ASUS_HANDLE_INIT(ls_switch))
 		ASUS_HANDLE_INIT(ls_level);
 
+	ASUS_HANDLE_INIT(gps_on);
+	ASUS_HANDLE_INIT(gps_off);
+	ASUS_HANDLE_INIT(gps_status);
+
 	kfree(model);
 
 	return AE_OK;
@@ -950,7 +1001,7 @@
 	 * We install the handler, it will receive the hotk in parameter, so, we
 	 * could add other data to the hotk struct
 	 */
-	status = acpi_install_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
+	status = acpi_install_notify_handler(hotk->handle, ACPI_ALL_NOTIFY,
 					     asus_hotk_notify, hotk);
 	if (ACPI_FAILURE(status))
 		printk(ASUS_ERR "Error installing notify handler\n");
@@ -981,6 +1032,9 @@
 	if (ls_level_handle)
 		set_light_sens_level(hotk->light_level);
 
+	/* GPS is on by default */
+	write_status(NULL, 1, GPS_ON);
+
       end:
 	if (result) {
 		kfree(hotk->name);
@@ -997,7 +1051,7 @@
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 
-	status = acpi_remove_notify_handler(hotk->handle, ACPI_SYSTEM_NOTIFY,
+	status = acpi_remove_notify_handler(hotk->handle, ACPI_ALL_NOTIFY,
 					    asus_hotk_notify);
 	if (ACPI_FAILURE(status))
 		printk(ASUS_ERR "Error removing notify handler\n");
diff --git a/drivers/misc/msi-laptop.c b/drivers/misc/msi-laptop.c
index 68c4b58..41e901f 100644
--- a/drivers/misc/msi-laptop.c
+++ b/drivers/misc/msi-laptop.c
@@ -85,7 +85,7 @@
 	buf[0] = 0x80;
 	buf[1] = (u8) (level*31);
 
-	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0);
+	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0, 1);
 }
 
 static int get_lcd_level(void)
@@ -93,7 +93,7 @@
 	u8 wdata = 0, rdata;
 	int result;
 
-	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1);
+	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1);
 	if (result < 0)
 		return result;
 
@@ -105,7 +105,7 @@
 	u8 wdata = 4, rdata;
 	int result;
 
-	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1);
+	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1, 1);
 	if (result < 0)
 		return result;
 
@@ -119,14 +119,14 @@
 
 	wdata[0] = 4;
 
-	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1);
+	result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1, 1);
 	if (result < 0)
 		return result;
 
 	wdata[0] = 0x84;
 	wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0);
 
-	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0);
+	return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1);
 }
 
 static int get_wireless_state(int *wlan, int *bluetooth)
@@ -134,7 +134,7 @@
 	u8 wdata = 0, rdata;
 	int result;
 
-	result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1);
+	result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1, 1);
 	if (result < 0)
 		return -1;
 
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c
index c15c1f6..8ee0321 100644
--- a/drivers/misc/sony-laptop.c
+++ b/drivers/misc/sony-laptop.c
@@ -63,7 +63,7 @@
 #include <asm/uaccess.h>
 #include <linux/sonypi.h>
 #include <linux/sony-laptop.h>
-#ifdef CONFIG_SONY_LAPTOP_OLD
+#ifdef CONFIG_SONYPI_COMPAT
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
 #endif
@@ -114,7 +114,7 @@
 		 "set this to 1 to enable Motion Eye camera controls "
 		 "(only use it if you have a C1VE or C1VN model)");
 
-#ifdef CONFIG_SONY_LAPTOP_OLD
+#ifdef CONFIG_SONYPI_COMPAT
 static int minor = -1;
 module_param(minor, int, 0);
 MODULE_PARM_DESC(minor,
@@ -1504,7 +1504,7 @@
 };
 
 /******** SONYPI compatibility **********/
-#ifdef CONFIG_SONY_LAPTOP_OLD
+#ifdef CONFIG_SONYPI_COMPAT
 
 /* battery / brightness / temperature  addresses */
 #define SONYPI_BAT_FLAGS	0x81
@@ -1798,7 +1798,7 @@
 static int sonypi_compat_init(void) { return 0; }
 static void sonypi_compat_exit(void) { }
 static void sonypi_compat_report_event(u8 event) { }
-#endif /* CONFIG_SONY_LAPTOP_OLD */
+#endif /* CONFIG_SONYPI_COMPAT */
 
 /*
  * ACPI callbacks
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 45b7d53..c0b41e8 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -4,6 +4,7 @@
 
 menuconfig MMC
 	tristate "MMC/SD card support"
+	depends on HAS_IOMEM
 	help
 	  MMC is the "multi-media card" bus protocol.
 
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index c1b47db..fbec8cd 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -2,6 +2,7 @@
 
 menuconfig MTD
 	tristate "Memory Technology Device (MTD) support"
+	depends on HAS_IOMEM
 	help
 	  Memory Technology Devices are flash, RAM and similar chips, often
 	  used for solid state file systems on embedded devices. This option
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index d0f2898..7540966 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -167,7 +167,7 @@
 
 	fep->ring_mem_addr = cpm_dpalloc((fpi->tx_ring + fpi->rx_ring) *
 					 sizeof(cbd_t), 8);
-	if (IS_DPERR(fep->ring_mem_addr))
+	if (IS_ERR_VALUE(fep->ring_mem_addr))
 		return -ENOMEM;
 
 	fep->ring_base = cpm_dpram_addr(fep->ring_mem_addr);
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 7c8ccc0..829da9a 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -141,6 +141,20 @@
 	  To activate support for ACTiSYS IR-200L dongle you will have to
 	  start irattach like this: "irattach -d act200l".
 
+config KINGSUN_DONGLE
+	tristate "KingSun/DonShine DS-620 IrDA-USB dongle"
+	depends on IRDA && USB && EXPERIMENTAL
+	help
+	  Say Y or M here if you want to build support for the KingSun/DonShine
+	  DS-620 IrDA-USB bridge device driver.
+
+	  This USB bridge does not conform to the IrDA-USB device class
+	  specification, and therefore needs its own specific driver. This
+	  dongle supports SIR speed only (9600 bps).
+
+	  To compile it as a module, choose M here: the module will be called
+	  kingsun-sir.
+
 comment "Old SIR device drivers"
 
 config IRPORT_SIR
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index 5be09f1..233a2f9 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -45,6 +45,7 @@
 obj-$(CONFIG_ACT200L_DONGLE)	+= act200l-sir.o
 obj-$(CONFIG_MA600_DONGLE)	+= ma600-sir.o
 obj-$(CONFIG_TOIM3232_DONGLE)	+= toim3232-sir.o
+obj-$(CONFIG_KINGSUN_DONGLE)	+= kingsun-sir.o
 
 # The SIR helper module
 sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
new file mode 100644
index 0000000..2174291
--- /dev/null
+++ b/drivers/net/irda/kingsun-sir.c
@@ -0,0 +1,657 @@
+/*****************************************************************************
+*
+* Filename:      kingsun-sir.c
+* Version:       0.1.1
+* Description:   Irda KingSun/DonShine USB Dongle
+* Status:        Experimental
+* Author:        Alex Villac�s Lasso <a_villacis@palosanto.com>
+*
+*  	Based on stir4200 and mcs7780 drivers, with (strange?) differences
+*
+*	This program is free software; you can redistribute it and/or modify
+*	it under the terms of the GNU General Public License as published by
+*	the Free Software Foundation; either version 2 of the License.
+*
+*	This program is distributed in the hope that it will be useful,
+*	but WITHOUT ANY WARRANTY; without even the implied warranty of
+*	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*	GNU General Public License for more details.
+*
+*	You should have received a copy of the GNU General Public License
+*	along with this program; if not, write to the Free Software
+*	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+*****************************************************************************/
+
+/*
+ * This is my current (2007-04-25) understanding of how this dongle is supposed
+ * to work. This is based on reverse-engineering and examination of the packet
+ * data sent and received by the WinXP driver using USBSnoopy. Feel free to
+ * update here as more of this dongle is known:
+ *
+ * General: Unlike the other USB IrDA dongles, this particular dongle exposes,
+ * not two bulk (in and out) endpoints, but two *interrupt* ones. This dongle,
+ * like the bulk based ones (stir4200.c and mcs7780.c), requires polling in
+ * order to receive data.
+ * Transmission: Just like stir4200, this dongle uses a raw stream of data,
+ * which needs to be wrapped and escaped in a similar way as in stir4200.c.
+ * Reception: Poll-based, as in stir4200. Each read returns the contents of a
+ * 8-byte buffer, of which the first byte (LSB) indicates the number of bytes
+ * (1-7) of valid data contained within the remaining 7 bytes. For example, if
+ * the buffer had the following contents:
+ *  06 ff ff ff c0 01 04 aa
+ * This means that (06) there are 6 bytes of valid data. The byte 0xaa at the
+ * end is garbage (left over from a previous reception) and is discarded.
+ * If a read returns an "impossible" value as the length of valid data (such as
+ * 0x36) in the first byte, then the buffer is uninitialized (as is the case of
+ * first plug-in) and its contents should be discarded. There is currently no
+ * evidence that the top 5 bits of the 1st byte of the buffer can have values
+ * other than 0 once reception begins.
+ * Once valid bytes are collected, the assembled stream is a sequence of
+ * wrapped IrDA frames that is unwrapped and unescaped as in stir4200.c.
+ * BIG FAT WARNING: the dongle does *not* reset the RX buffer in any way after
+ * a successful read from the host, which means that in absence of further
+ * reception, repeated reads from the dongle will return the exact same
+ * contents repeatedly. Attempts to be smart and cache a previous read seem
+ * to result in corrupted packets, so this driver depends on the unwrap logic
+ * to sort out any repeated reads.
+ * Speed change: no commands observed so far to change speed, assumed fixed
+ * 9600bps (SIR).
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/device.h>
+#include <linux/crc32.h>
+
+#include <asm/unaligned.h>
+#include <asm/byteorder.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/crc.h>
+
+/*
+ * According to lsusb, 0x07c0 is assigned to
+ * "Code Mercenaries Hard- und Software GmbH"
+ */
+#define KING_VENDOR_ID 0x07c0
+#define KING_PRODUCT_ID 0x4200
+
+/* These are the currently known USB ids */
+static struct usb_device_id dongles[] = {
+    /* KingSun Co,Ltd  IrDA/USB Bridge */
+    { USB_DEVICE(KING_VENDOR_ID, KING_PRODUCT_ID) },
+    { }
+};
+
+MODULE_DEVICE_TABLE(usb, dongles);
+
+#define KINGSUN_MTT 0x07
+
+#define KINGSUN_FIFO_SIZE		4096
+#define KINGSUN_EP_IN			0
+#define KINGSUN_EP_OUT			1
+
+struct kingsun_cb {
+	struct usb_device *usbdev;      /* init: probe_irda */
+	struct net_device *netdev;      /* network layer */
+	struct irlap_cb   *irlap;       /* The link layer we are binded to */
+	struct net_device_stats stats;	/* network statistics */
+	struct qos_info   qos;
+
+	__u8		  *in_buf;	/* receive buffer */
+	__u8		  *out_buf;	/* transmit buffer */
+	__u8		  max_rx;	/* max. atomic read from dongle
+					   (usually 8), also size of in_buf */
+	__u8		  max_tx;	/* max. atomic write to dongle
+					   (usually 8) */
+
+	iobuff_t  	  rx_buff;	/* receive unwrap state machine */
+	struct timeval	  rx_time;
+	spinlock_t lock;
+	int receiving;
+
+	__u8 ep_in;
+	__u8 ep_out;
+
+	struct urb	 *tx_urb;
+	struct urb	 *rx_urb;
+};
+
+/* Callback transmission routine */
+static void kingsun_send_irq(struct urb *urb)
+{
+	struct kingsun_cb *kingsun = urb->context;
+	struct net_device *netdev = kingsun->netdev;
+
+	/* in process of stopping, just drop data */
+	if (!netif_running(kingsun->netdev)) {
+		err("kingsun_send_irq: Network not running!");
+		return;
+	}
+
+	/* unlink, shutdown, unplug, other nasties */
+	if (urb->status != 0) {
+		err("kingsun_send_irq: urb asynchronously failed - %d",
+		    urb->status);
+	}
+	netif_wake_queue(netdev);
+}
+
+/*
+ * Called from net/core when new frame is available.
+ */
+static int kingsun_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct kingsun_cb *kingsun;
+	int wraplen;
+	int ret = 0;
+
+	if (skb == NULL || netdev == NULL)
+		return -EINVAL;
+
+	netif_stop_queue(netdev);
+
+	/* the IRDA wrapping routines don't deal with non linear skb */
+	SKB_LINEAR_ASSERT(skb);
+
+	kingsun = netdev_priv(netdev);
+
+	spin_lock(&kingsun->lock);
+
+	/* Append data to the end of whatever data remains to be transmitted */
+	wraplen = async_wrap_skb(skb,
+		kingsun->out_buf,
+		KINGSUN_FIFO_SIZE);
+
+	/* Calculate how much data can be transmitted in this urb */
+	usb_fill_int_urb(kingsun->tx_urb, kingsun->usbdev,
+		usb_sndintpipe(kingsun->usbdev, kingsun->ep_out),
+		kingsun->out_buf, wraplen, kingsun_send_irq,
+		kingsun, 1);
+
+	if ((ret = usb_submit_urb(kingsun->tx_urb, GFP_ATOMIC))) {
+		err("kingsun_hard_xmit: failed tx_urb submit: %d", ret);
+		switch (ret) {
+		case -ENODEV:
+		case -EPIPE:
+			break;
+		default:
+			kingsun->stats.tx_errors++;
+			netif_start_queue(netdev);
+		}
+	} else {
+		kingsun->stats.tx_packets++;
+		kingsun->stats.tx_bytes += skb->len;
+	}
+
+	dev_kfree_skb(skb);
+	spin_unlock(&kingsun->lock);
+
+	return ret;
+}
+
+/* Receive callback function */
+static void kingsun_rcv_irq(struct urb *urb)
+{
+	struct kingsun_cb *kingsun = urb->context;
+	int ret;
+
+	/* in process of stopping, just drop data */
+	if (!netif_running(kingsun->netdev)) {
+		kingsun->receiving = 0;
+		return;
+	}
+
+	/* unlink, shutdown, unplug, other nasties */
+	if (urb->status != 0) {
+		err("kingsun_rcv_irq: urb asynchronously failed - %d",
+		    urb->status);
+		kingsun->receiving = 0;
+		return;
+	}
+
+	if (urb->actual_length == kingsun->max_rx) {
+		__u8 *bytes = urb->transfer_buffer;
+		int i;
+
+		/* The very first byte in the buffer indicates the length of
+		   valid data in the read. This byte must be in the range
+		   1..kingsun->max_rx -1 . Values outside this range indicate
+		   an uninitialized Rx buffer when the dongle has just been
+		   plugged in. */
+		if (bytes[0] >= 1 && bytes[0] < kingsun->max_rx) {
+			for (i = 1; i <= bytes[0]; i++) {
+				async_unwrap_char(kingsun->netdev,
+						  &kingsun->stats,
+						  &kingsun->rx_buff, bytes[i]);
+			}
+			kingsun->netdev->last_rx = jiffies;
+			do_gettimeofday(&kingsun->rx_time);
+			kingsun->receiving =
+				(kingsun->rx_buff.state != OUTSIDE_FRAME)
+				? 1 : 0;
+		}
+	} else if (urb->actual_length > 0) {
+		err("%s(): Unexpected response length, expected %d got %d",
+		    __FUNCTION__, kingsun->max_rx, urb->actual_length);
+	}
+	/* This urb has already been filled in kingsun_net_open */
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+/*
+ * Function kingsun_net_open (dev)
+ *
+ *    Network device is taken up. Usually this is done by "ifconfig irda0 up"
+ */
+static int kingsun_net_open(struct net_device *netdev)
+{
+	struct kingsun_cb *kingsun = netdev_priv(netdev);
+	int err = -ENOMEM;
+	char hwname[16];
+
+	/* At this point, urbs are NULL, and skb is NULL (see kingsun_probe) */
+	kingsun->receiving = 0;
+
+	/* Initialize for SIR to copy data directly into skb.  */
+	kingsun->rx_buff.in_frame = FALSE;
+	kingsun->rx_buff.state = OUTSIDE_FRAME;
+	kingsun->rx_buff.truesize = IRDA_SKB_MAX_MTU;
+	kingsun->rx_buff.skb = dev_alloc_skb(IRDA_SKB_MAX_MTU);
+	if (!kingsun->rx_buff.skb)
+		goto free_mem;
+
+	skb_reserve(kingsun->rx_buff.skb, 1);
+	kingsun->rx_buff.head = kingsun->rx_buff.skb->data;
+	do_gettimeofday(&kingsun->rx_time);
+
+	kingsun->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!kingsun->rx_urb)
+		goto free_mem;
+
+	kingsun->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!kingsun->tx_urb)
+		goto free_mem;
+
+	/*
+	 * Now that everything should be initialized properly,
+	 * Open new IrLAP layer instance to take care of us...
+	 */
+	sprintf(hwname, "usb#%d", kingsun->usbdev->devnum);
+	kingsun->irlap = irlap_open(netdev, &kingsun->qos, hwname);
+	if (!kingsun->irlap) {
+		err("kingsun-sir: irlap_open failed");
+		goto free_mem;
+	}
+
+	/* Start first reception */
+	usb_fill_int_urb(kingsun->rx_urb, kingsun->usbdev,
+			  usb_rcvintpipe(kingsun->usbdev, kingsun->ep_in),
+			  kingsun->in_buf, kingsun->max_rx,
+			  kingsun_rcv_irq, kingsun, 1);
+	kingsun->rx_urb->status = 0;
+	err = usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+	if (err) {
+		err("kingsun-sir: first urb-submit failed: %d", err);
+		goto close_irlap;
+	}
+
+	netif_start_queue(netdev);
+
+	/* Situation at this point:
+	   - all work buffers allocated
+	   - urbs allocated and ready to fill
+	   - max rx packet known (in max_rx)
+	   - unwrap state machine initialized, in state outside of any frame
+	   - receive request in progress
+	   - IrLAP layer started, about to hand over packets to send
+	 */
+
+	return 0;
+
+ close_irlap:
+	irlap_close(kingsun->irlap);
+ free_mem:
+	if (kingsun->tx_urb) {
+		usb_free_urb(kingsun->tx_urb);
+		kingsun->tx_urb = NULL;
+	}
+	if (kingsun->rx_urb) {
+		usb_free_urb(kingsun->rx_urb);
+		kingsun->rx_urb = NULL;
+	}
+	if (kingsun->rx_buff.skb) {
+		kfree_skb(kingsun->rx_buff.skb);
+		kingsun->rx_buff.skb = NULL;
+		kingsun->rx_buff.head = NULL;
+	}
+	return err;
+}
+
+/*
+ * Function kingsun_net_close (kingsun)
+ *
+ *    Network device is taken down. Usually this is done by
+ *    "ifconfig irda0 down"
+ */
+static int kingsun_net_close(struct net_device *netdev)
+{
+	struct kingsun_cb *kingsun = netdev_priv(netdev);
+
+	/* Stop transmit processing */
+	netif_stop_queue(netdev);
+
+	/* Mop up receive && transmit urb's */
+	usb_kill_urb(kingsun->tx_urb);
+	usb_kill_urb(kingsun->rx_urb);
+
+	usb_free_urb(kingsun->tx_urb);
+	usb_free_urb(kingsun->rx_urb);
+
+	kingsun->tx_urb = NULL;
+	kingsun->rx_urb = NULL;
+
+	kfree_skb(kingsun->rx_buff.skb);
+	kingsun->rx_buff.skb = NULL;
+	kingsun->rx_buff.head = NULL;
+	kingsun->rx_buff.in_frame = FALSE;
+	kingsun->rx_buff.state = OUTSIDE_FRAME;
+	kingsun->receiving = 0;
+
+	/* Stop and remove instance of IrLAP */
+	if (kingsun->irlap)
+		irlap_close(kingsun->irlap);
+
+	kingsun->irlap = NULL;
+
+	return 0;
+}
+
+/*
+ * IOCTLs : Extra out-of-band network commands...
+ */
+static int kingsun_net_ioctl(struct net_device *netdev, struct ifreq *rq,
+			     int cmd)
+{
+	struct if_irda_req *irq = (struct if_irda_req *) rq;
+	struct kingsun_cb *kingsun = netdev_priv(netdev);
+	int ret = 0;
+
+	switch (cmd) {
+	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		/* Check if the device is still there */
+		if (netif_device_present(kingsun->netdev))
+			/* No observed commands for speed change */
+			ret = -EOPNOTSUPP;
+		break;
+
+	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+
+		/* Check if the IrDA stack is still there */
+		if (netif_running(kingsun->netdev))
+			irda_device_set_media_busy(kingsun->netdev, TRUE);
+		break;
+
+	case SIOCGRECEIVING:
+		/* Only approximately true */
+		irq->ifr_receiving = kingsun->receiving;
+		break;
+
+	default:
+		ret = -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+/*
+ * Get device stats (for /proc/net/dev and ifconfig)
+ */
+static struct net_device_stats *
+kingsun_net_get_stats(struct net_device *netdev)
+{
+	struct kingsun_cb *kingsun = netdev_priv(netdev);
+	return &kingsun->stats;
+}
+
+/*
+ * This routine is called by the USB subsystem for each new device
+ * in the system. We need to check if the device is ours, and in
+ * this case start handling it.
+ */
+static int kingsun_probe(struct usb_interface *intf,
+		      const struct usb_device_id *id)
+{
+	struct usb_host_interface *interface;
+	struct usb_endpoint_descriptor *endpoint;
+
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct kingsun_cb *kingsun = NULL;
+	struct net_device *net = NULL;
+	int ret = -ENOMEM;
+	int pipe, maxp_in, maxp_out;
+	__u8 ep_in;
+	__u8 ep_out;
+
+	/* Check that there really are two interrupt endpoints.
+	   Check based on the one in drivers/usb/input/usbmouse.c
+	 */
+	interface = intf->cur_altsetting;
+	if (interface->desc.bNumEndpoints != 2) {
+		err("kingsun-sir: expected 2 endpoints, found %d",
+		    interface->desc.bNumEndpoints);
+		return -ENODEV;
+	}
+	endpoint = &interface->endpoint[KINGSUN_EP_IN].desc;
+	if (!usb_endpoint_is_int_in(endpoint)) {
+		err("kingsun-sir: endpoint 0 is not interrupt IN");
+		return -ENODEV;
+	}
+
+	ep_in = endpoint->bEndpointAddress;
+	pipe = usb_rcvintpipe(dev, ep_in);
+	maxp_in = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+	if (maxp_in > 255 || maxp_in <= 1) {
+		err("%s: endpoint 0 has max packet size %d not in range",
+		    __FILE__, maxp_in);
+		return -ENODEV;
+	}
+
+	endpoint = &interface->endpoint[KINGSUN_EP_OUT].desc;
+	if (!usb_endpoint_is_int_out(endpoint)) {
+		err("kingsun-sir: endpoint 1 is not interrupt OUT");
+		return -ENODEV;
+	}
+
+	ep_out = endpoint->bEndpointAddress;
+	pipe = usb_sndintpipe(dev, ep_out);
+	maxp_out = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+
+	/* Allocate network device container. */
+	net = alloc_irdadev(sizeof(*kingsun));
+	if(!net)
+		goto err_out1;
+
+	SET_MODULE_OWNER(net);
+	SET_NETDEV_DEV(net, &intf->dev);
+	kingsun = netdev_priv(net);
+	kingsun->irlap = NULL;
+	kingsun->tx_urb = NULL;
+	kingsun->rx_urb = NULL;
+	kingsun->ep_in = ep_in;
+	kingsun->ep_out = ep_out;
+	kingsun->in_buf = NULL;
+	kingsun->out_buf = NULL;
+	kingsun->max_rx = (__u8)maxp_in;
+	kingsun->max_tx = (__u8)maxp_out;
+	kingsun->netdev = net;
+	kingsun->usbdev = dev;
+	kingsun->rx_buff.in_frame = FALSE;
+	kingsun->rx_buff.state = OUTSIDE_FRAME;
+	kingsun->rx_buff.skb = NULL;
+	kingsun->receiving = 0;
+	spin_lock_init(&kingsun->lock);
+
+	/* Allocate input buffer */
+	kingsun->in_buf = (__u8 *)kmalloc(kingsun->max_rx, GFP_KERNEL);
+	if (!kingsun->in_buf)
+		goto free_mem;
+
+	/* Allocate output buffer */
+	kingsun->out_buf = (__u8 *)kmalloc(KINGSUN_FIFO_SIZE, GFP_KERNEL);
+	if (!kingsun->out_buf)
+		goto free_mem;
+
+	printk(KERN_INFO "KingSun/DonShine IRDA/USB found at address %d, "
+		"Vendor: %x, Product: %x\n",
+	       dev->devnum, le16_to_cpu(dev->descriptor.idVendor),
+	       le16_to_cpu(dev->descriptor.idProduct));
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies(&kingsun->qos);
+
+	/* That's the Rx capability. */
+	kingsun->qos.baud_rate.bits       &= IR_9600;
+	kingsun->qos.min_turn_time.bits   &= KINGSUN_MTT;
+	irda_qos_bits_to_value(&kingsun->qos);
+
+	/* Override the network functions we need to use */
+	net->hard_start_xmit = kingsun_hard_xmit;
+	net->open            = kingsun_net_open;
+	net->stop            = kingsun_net_close;
+	net->get_stats	     = kingsun_net_get_stats;
+	net->do_ioctl        = kingsun_net_ioctl;
+
+	ret = register_netdev(net);
+	if (ret != 0)
+		goto free_mem;
+
+	info("IrDA: Registered KingSun/DonShine device %s", net->name);
+
+	usb_set_intfdata(intf, kingsun);
+
+	/* Situation at this point:
+	   - all work buffers allocated
+	   - urbs not allocated, set to NULL
+	   - max rx packet known (in max_rx)
+	   - unwrap state machine (partially) initialized, but skb == NULL
+	 */
+
+	return 0;
+
+free_mem:
+	if (kingsun->out_buf) kfree(kingsun->out_buf);
+	if (kingsun->in_buf) kfree(kingsun->in_buf);
+	free_netdev(net);
+err_out1:
+	return ret;
+}
+
+/*
+ * The current device is removed, the USB layer tell us to shut it down...
+ */
+static void kingsun_disconnect(struct usb_interface *intf)
+{
+	struct kingsun_cb *kingsun = usb_get_intfdata(intf);
+
+	if (!kingsun)
+		return;
+
+	unregister_netdev(kingsun->netdev);
+
+	/* Mop up receive && transmit urb's */
+	if (kingsun->tx_urb != NULL) {
+		usb_kill_urb(kingsun->tx_urb);
+		usb_free_urb(kingsun->tx_urb);
+		kingsun->tx_urb = NULL;
+	}
+	if (kingsun->rx_urb != NULL) {
+		usb_kill_urb(kingsun->rx_urb);
+		usb_free_urb(kingsun->rx_urb);
+		kingsun->rx_urb = NULL;
+	}
+
+	kfree(kingsun->out_buf);
+	kfree(kingsun->in_buf);
+	free_netdev(kingsun->netdev);
+
+	usb_set_intfdata(intf, NULL);
+}
+
+#ifdef CONFIG_PM
+/* USB suspend, so power off the transmitter/receiver */
+static int kingsun_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct kingsun_cb *kingsun = usb_get_intfdata(intf);
+
+	netif_device_detach(kingsun->netdev);
+	if (kingsun->tx_urb != NULL) usb_kill_urb(kingsun->tx_urb);
+	if (kingsun->rx_urb != NULL) usb_kill_urb(kingsun->rx_urb);
+	return 0;
+}
+
+/* Coming out of suspend, so reset hardware */
+static int kingsun_resume(struct usb_interface *intf)
+{
+	struct kingsun_cb *kingsun = usb_get_intfdata(intf);
+
+	if (kingsun->rx_urb != NULL)
+		usb_submit_urb(kingsun->rx_urb, GFP_KERNEL);
+	netif_device_attach(kingsun->netdev);
+
+	return 0;
+}
+#endif
+
+/*
+ * USB device callbacks
+ */
+static struct usb_driver irda_driver = {
+	.name		= "kingsun-sir",
+	.probe		= kingsun_probe,
+	.disconnect	= kingsun_disconnect,
+	.id_table	= dongles,
+#ifdef CONFIG_PM
+	.suspend	= kingsun_suspend,
+	.resume		= kingsun_resume,
+#endif
+};
+
+/*
+ * Module insertion
+ */
+static int __init kingsun_init(void)
+{
+	return usb_register(&irda_driver);
+}
+module_init(kingsun_init);
+
+/*
+ * Module removal
+ */
+static void __exit kingsun_cleanup(void)
+{
+	/* Deregister the driver and remove all pending instances */
+	usb_deregister(&irda_driver);
+}
+module_exit(kingsun_cleanup);
+
+MODULE_AUTHOR("Alex Villac�s Lasso <a_villacis@palosanto.com>");
+MODULE_DESCRIPTION("IrDA-USB Dongle Driver for KingSun/DonShine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index f994f12..c0d3101 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "PHY device support"
+	depends on !S390
 
 config PHYLIB
 	tristate "PHY Device support and infrastructure"
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 1fc7730..2106bec 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -16,11 +16,13 @@
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
+#include <linux/platform_device.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ip22.h>
+#include <asm/sgi/seeq.h>
 
 #include "sgiseeq.h"
 
@@ -92,13 +94,9 @@
 
 	struct net_device_stats stats;
 
-	struct net_device *next_module;
 	spinlock_t tx_lock;
 };
 
-/* A list of all installed seeq devices, for removing the driver module. */
-static struct net_device *root_sgiseeq_dev;
-
 static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
 {
 	hregs->reset = HPC3_ERST_CRESET | HPC3_ERST_CLRIRQ;
@@ -624,9 +622,12 @@
 
 #define ALIGNED(x)  ((((unsigned long)(x)) + 0xf) & ~(0xf))
 
-static int sgiseeq_init(struct hpc3_regs* hpcregs, int irq, int has_eeprom)
+static int __init sgiseeq_probe(struct platform_device *pdev)
 {
+	struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
+	struct hpc3_regs *hpcregs = pd->hpc;
 	struct sgiseeq_init_block *sr;
+	unsigned int irq = pd->irq;
 	struct sgiseeq_private *sp;
 	struct net_device *dev;
 	int err, i;
@@ -637,6 +638,8 @@
 		err = -ENOMEM;
 		goto err_out;
 	}
+
+	platform_set_drvdata(pdev, dev);
 	sp = netdev_priv(dev);
 
 	/* Make private data page aligned */
@@ -648,15 +651,7 @@
 	}
 	sp->srings = sr;
 
-#define EADDR_NVOFS     250
-	for (i = 0; i < 3; i++) {
-		unsigned short tmp = has_eeprom ?
-			ip22_eeprom_read(&hpcregs->eeprom, EADDR_NVOFS / 2+i) :
-			ip22_nvram_read(EADDR_NVOFS / 2+i);
-
-		dev->dev_addr[2 * i]     = tmp >> 8;
-		dev->dev_addr[2 * i + 1] = tmp & 0xff;
-	}
+	memcpy(dev->dev_addr, pd->mac, ETH_ALEN);
 
 #ifdef DEBUG
 	gpriv = sp;
@@ -720,9 +715,6 @@
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
 
-	sp->next_module = root_sgiseeq_dev;
-	root_sgiseeq_dev = dev;
-
 	return 0;
 
 err_out_free_page:
@@ -734,43 +726,42 @@
 	return err;
 }
 
-static int __init sgiseeq_probe(void)
+static void __exit sgiseeq_remove(struct platform_device *pdev)
 {
-	unsigned int tmp, ret1, ret2 = 0;
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct sgiseeq_private *sp = netdev_priv(dev);
 
-	/* On board adapter on 1st HPC is always present */
-	ret1 = sgiseeq_init(hpc3c0, SGI_ENET_IRQ, 0);
-	/* Let's see if second HPC is there */
-	if (!(ip22_is_fullhouse()) &&
-	    get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]) == 0) {
-		sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 |
-				 SGIMC_GIOPAR_EXP164 |
-				 SGIMC_GIOPAR_HPC264;
-		hpc3c1->pbus_piocfg[0][0] = 0x3ffff;
-		/* interrupt/config register on Challenge S Mezz board */
-		hpc3c1->pbus_extregs[0][0] = 0x30;
-		ret2 = sgiseeq_init(hpc3c1, SGI_GIO_0_IRQ, 1);
-	}
-
-	return (ret1 & ret2) ? ret1 : 0;
+	unregister_netdev(dev);
+	free_page((unsigned long) sp->srings);
+	free_netdev(dev);
+	platform_set_drvdata(pdev, NULL);
 }
 
-static void __exit sgiseeq_exit(void)
-{
-	struct net_device *next, *dev;
-	struct sgiseeq_private *sp;
-
-	for (dev = root_sgiseeq_dev; dev; dev = next) {
-		sp = (struct sgiseeq_private *) netdev_priv(dev);
-		next = sp->next_module;
-		unregister_netdev(dev);
-		free_page((unsigned long) sp->srings);
-		free_netdev(dev);
+static struct platform_driver sgiseeq_driver = {
+	.probe	= sgiseeq_probe,
+	.remove	= __devexit_p(sgiseeq_remove),
+	.driver = {
+		.name	= "sgiseeq"
 	}
+};
+
+static int __init sgiseeq_module_init(void)
+{
+	if (platform_driver_register(&sgiseeq_driver)) {
+		printk(KERN_ERR "Driver registration failed\n");
+		return -ENODEV;
+	}
+
+	return 0;
 }
 
-module_init(sgiseeq_probe);
-module_exit(sgiseeq_exit);
+static void __exit sgiseeq_module_exit(void)
+{
+	platform_driver_unregister(&sgiseeq_driver);
+}
+
+module_init(sgiseeq_module_init);
+module_exit(sgiseeq_module_exit);
 
 MODULE_DESCRIPTION("SGI Seeq 8003 driver");
 MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>");
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index d7aff81..0f66765 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -293,7 +293,7 @@
 		else {
 			init_enet_offset =
 			    qe_muram_alloc(thread_size, thread_alignment);
-			if (IS_MURAM_ERR(init_enet_offset)) {
+			if (IS_ERR_VALUE(init_enet_offset)) {
 				ugeth_err
 		("fill_init_enet_entries: Can not allocate DPRAM memory.");
 				qe_put_snum((u8) snum);
@@ -2594,7 +2594,7 @@
 			ugeth->tx_bd_ring_offset[j] =
 			    qe_muram_alloc(length,
 					   UCC_GETH_TX_BD_RING_ALIGNMENT);
-			if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j]))
+			if (!IS_ERR_VALUE(ugeth->tx_bd_ring_offset[j]))
 				ugeth->p_tx_bd_ring[j] =
 				    (u8 *) qe_muram_addr(ugeth->
 							 tx_bd_ring_offset[j]);
@@ -2629,7 +2629,7 @@
 			ugeth->rx_bd_ring_offset[j] =
 			    qe_muram_alloc(length,
 					   UCC_GETH_RX_BD_RING_ALIGNMENT);
-			if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j]))
+			if (!IS_ERR_VALUE(ugeth->rx_bd_ring_offset[j]))
 				ugeth->p_rx_bd_ring[j] =
 				    (u8 *) qe_muram_addr(ugeth->
 							 rx_bd_ring_offset[j]);
@@ -2713,7 +2713,7 @@
 	ugeth->tx_glbl_pram_offset =
 	    qe_muram_alloc(sizeof(struct ucc_geth_tx_global_pram),
 			   UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) {
+	if (IS_ERR_VALUE(ugeth->tx_glbl_pram_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
 		     __FUNCTION__);
@@ -2735,7 +2735,7 @@
 			   sizeof(struct ucc_geth_thread_data_tx) +
 			   32 * (numThreadsTxNumerical == 1),
 			   UCC_GETH_THREAD_DATA_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) {
+	if (IS_ERR_VALUE(ugeth->thread_dat_tx_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
 		     __FUNCTION__);
@@ -2763,7 +2763,7 @@
 	    qe_muram_alloc(ug_info->numQueuesTx *
 			   sizeof(struct ucc_geth_send_queue_qd),
 			   UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) {
+	if (IS_ERR_VALUE(ugeth->send_q_mem_reg_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
 		     __FUNCTION__);
@@ -2806,7 +2806,7 @@
 		ugeth->scheduler_offset =
 		    qe_muram_alloc(sizeof(struct ucc_geth_scheduler),
 				   UCC_GETH_SCHEDULER_ALIGNMENT);
-		if (IS_MURAM_ERR(ugeth->scheduler_offset)) {
+		if (IS_ERR_VALUE(ugeth->scheduler_offset)) {
 			ugeth_err
 			 ("%s: Can not allocate DPRAM memory for p_scheduler.",
 			     __FUNCTION__);
@@ -2854,7 +2854,7 @@
 		    qe_muram_alloc(sizeof
 				   (struct ucc_geth_tx_firmware_statistics_pram),
 				   UCC_GETH_TX_STATISTICS_ALIGNMENT);
-		if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) {
+		if (IS_ERR_VALUE(ugeth->tx_fw_statistics_pram_offset)) {
 			ugeth_err
 			    ("%s: Can not allocate DPRAM memory for"
 				" p_tx_fw_statistics_pram.", __FUNCTION__);
@@ -2893,7 +2893,7 @@
 	ugeth->rx_glbl_pram_offset =
 	    qe_muram_alloc(sizeof(struct ucc_geth_rx_global_pram),
 			   UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) {
+	if (IS_ERR_VALUE(ugeth->rx_glbl_pram_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
 		     __FUNCTION__);
@@ -2914,7 +2914,7 @@
 	    qe_muram_alloc(numThreadsRxNumerical *
 			   sizeof(struct ucc_geth_thread_data_rx),
 			   UCC_GETH_THREAD_DATA_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) {
+	if (IS_ERR_VALUE(ugeth->thread_dat_rx_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
 		     __FUNCTION__);
@@ -2937,7 +2937,7 @@
 		    qe_muram_alloc(sizeof
 				   (struct ucc_geth_rx_firmware_statistics_pram),
 				   UCC_GETH_RX_STATISTICS_ALIGNMENT);
-		if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) {
+		if (IS_ERR_VALUE(ugeth->rx_fw_statistics_pram_offset)) {
 			ugeth_err
 				("%s: Can not allocate DPRAM memory for"
 				" p_rx_fw_statistics_pram.", __FUNCTION__);
@@ -2959,7 +2959,7 @@
 	    qe_muram_alloc(ug_info->numQueuesRx *
 			   sizeof(struct ucc_geth_rx_interrupt_coalescing_entry)
 			   + 4, UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) {
+	if (IS_ERR_VALUE(ugeth->rx_irq_coalescing_tbl_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for"
 			" p_rx_irq_coalescing_tbl.", __FUNCTION__);
@@ -3027,7 +3027,7 @@
 			   (sizeof(struct ucc_geth_rx_bd_queues_entry) +
 			    sizeof(struct ucc_geth_rx_prefetched_bds)),
 			   UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
-	if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) {
+	if (IS_ERR_VALUE(ugeth->rx_bd_qs_tbl_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
 		     __FUNCTION__);
@@ -3116,7 +3116,7 @@
 		ugeth->exf_glbl_param_offset =
 		    qe_muram_alloc(sizeof(struct ucc_geth_exf_global_pram),
 		UCC_GETH_RX_EXTENDED_FILTERING_GLOBAL_PARAMETERS_ALIGNMENT);
-		if (IS_MURAM_ERR(ugeth->exf_glbl_param_offset)) {
+		if (IS_ERR_VALUE(ugeth->exf_glbl_param_offset)) {
 			ugeth_err
 				("%s: Can not allocate DPRAM memory for"
 				" p_exf_glbl_param.", __FUNCTION__);
@@ -3258,7 +3258,7 @@
 
 	/* Allocate InitEnet command parameter structure */
 	init_enet_pram_offset = qe_muram_alloc(sizeof(struct ucc_geth_init_pram), 4);
-	if (IS_MURAM_ERR(init_enet_pram_offset)) {
+	if (IS_ERR_VALUE(init_enet_pram_offset)) {
 		ugeth_err
 		    ("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
 		     __FUNCTION__);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index e273347..e3f5bb0 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Wireless LAN"
+	depends on !S390
 
 config WLAN_PRE80211
 	bool "Wireless LAN (pre-802.11)"
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 36c6a1b..f46c69e4 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -6,6 +6,7 @@
 #
 
 menu "Parallel port support"
+	depends on HAS_IOMEM
 
 config PARPORT
 	tristate "Parallel port support"
diff --git a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig
index c514320..1959cef 100644
--- a/drivers/pnp/Kconfig
+++ b/drivers/pnp/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Plug and Play support"
+	depends on HAS_IOMEM
 
 config PNP
 	bool "Plug and Play support"
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 76422ed..95ce8f4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Real Time Clock"
+	depends on !S390
 
 config RTC_LIB
 	tristate
@@ -245,7 +246,7 @@
 config RTC_DRV_CMOS
 	tristate "PC-style 'CMOS'"
 	depends on RTC_CLASS && (X86 || ALPHA || ARM26 || ARM \
-		|| M32R || ATARI || POWERPC)
+		|| M32R || ATARI || POWERPC || MIPS)
 	help
 	  Say "yes" here to get direct support for the real time clock
 	  found in every PC or ACPI-based system, and some other boards.
@@ -396,7 +397,7 @@
 
 config RTC_DRV_RS5C313
 	tristate "Ricoh RS5C313"
-	depends on RTC_CLASS && BROKEN
+	depends on RTC_CLASS && SH_LANDISK
 	help
 	  If you say yes here you get support for the Ricoh RS5C313 RTC chips.
 
diff --git a/drivers/rtc/rtc-rs5c313.c b/drivers/rtc/rtc-rs5c313.c
index 9d6de37..66eb133 100644
--- a/drivers/rtc/rtc-rs5c313.c
+++ b/drivers/rtc/rtc-rs5c313.c
@@ -126,7 +126,7 @@
 static unsigned char rs5c313_read_data(void)
 {
 	int i;
-	unsigned char data;
+	unsigned char data = 0;
 
 	for (i = 0; i < 8; i++) {
 		ndelay(700);
@@ -194,7 +194,7 @@
 	return;
 }
 
-static inline unsigned char rs5c313_read_cntreg(unsigned char addr)
+static inline unsigned char rs5c313_read_cntreg(void)
 {
 	return rs5c313_read_reg(RS5C313_ADDR_CNTREG);
 }
@@ -212,7 +212,9 @@
 static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	int data;
+	int cnt;
 
+	cnt = 0;
 	while (1) {
 		RS5C313_CEENABLE;	/* CE:H */
 
@@ -225,6 +227,10 @@
 		RS5C313_CEDISABLE;
 		ndelay(700);	/* CE:L */
 
+		if (cnt++ > 100) {
+			dev_err(dev, "%s: timeout error\n", __FUNCTION__);
+			return -EIO;
+		}
 	}
 
 	data = rs5c313_read_reg(RS5C313_ADDR_SEC);
@@ -266,7 +272,9 @@
 static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	int data;
+	int cnt;
 
+	cnt = 0;
 	/* busy check. */
 	while (1) {
 		RS5C313_CEENABLE;	/* CE:H */
@@ -279,6 +287,11 @@
 		RS5C313_MISCOP;
 		RS5C313_CEDISABLE;
 		ndelay(700);	/* CE:L */
+
+		if (cnt++ > 100) {
+			dev_err(dev, "%s: timeout error\n", __FUNCTION__);
+			return -EIO;
+		}
 	}
 
 	data = BIN2BCD(tm->tm_sec);
@@ -317,6 +330,7 @@
 static void rs5c313_check_xstp_bit(void)
 {
 	struct rtc_time tm;
+	int cnt;
 
 	RS5C313_CEENABLE;	/* CE:H */
 	if (rs5c313_read_cntreg() & RS5C313_CNTREG_WTEN_XSTP) {
@@ -326,12 +340,16 @@
 		rs5c313_write_cntreg(0x07);
 
 		/* busy check. */
-		while (rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY)
+		for (cnt = 0; cnt < 100; cnt++) {
+			if (!(rs5c313_read_cntreg() & RS5C313_CNTREG_ADJ_BSY))
+				break;
 			RS5C313_MISCOP;
+		}
 
 		memset(&tm, 0, sizeof(struct rtc_time));
 		tm.tm_mday 	= 1;
-		tm.tm_mon 	= 1;
+		tm.tm_mon 	= 1 - 1;
+		tm.tm_year 	= 2000 - 1900;
 
 		rs5c313_rtc_set_time(NULL, &tm);
 		printk(KERN_ERR "RICHO RS5C313: invalid value, resetting to "
@@ -356,7 +374,7 @@
 
 	platform_set_drvdata(pdev, rtc);
 
-	return err;
+	return 0;
 }
 
 static int __devexit rs5c313_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
deleted file mode 100644
index 165af39..0000000
--- a/drivers/s390/Kconfig
+++ /dev/null
@@ -1,239 +0,0 @@
-config CCW
-	bool
-	default y
-
-source "drivers/block/Kconfig"
-
-source "drivers/md/Kconfig"
-
-
-menu "Character device drivers"
-
-config UNIX98_PTYS
-	bool "Unix98 PTY support"
-	---help---
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  The entries in /dev/pts/ are created on the fly by a virtual
-	  file system; therefore, if you say Y here you should say Y to
-	  "/dev/pts file system for Unix98 PTYs" as well.
-
-	  If you want to say Y here, you need to have the C library glibc 2.1
-	  or later (equal to libc-6.1, check with "ls -l /lib/libc.so.*").
-	  Read the instructions in <file:Documentation/Changes> pertaining to
-	  pseudo terminals. It's safe to say N.
-
-config UNIX98_PTY_COUNT
-	int "Maximum number of Unix98 PTYs in use (0-2048)"
-	depends on UNIX98_PTYS
-	default "256"
-	help
-	  The maximum number of Unix98 PTYs that can be used at any one time.
-	  The default is 256, and should be enough for desktop systems. Server
-	  machines which support incoming telnet/rlogin/ssh connections and/or
-	  serve several X terminals may want to increase this: every incoming
-	  connection and every xterm uses up one PTY.
-
-	  When not in use, each additional set of 256 PTYs occupy
-	  approximately 8 KB of kernel memory on 32-bit architectures.
-
-config HANGCHECK_TIMER
-	tristate "Hangcheck timer"
-	help
-	  The hangcheck-timer module detects when the system has gone
-	  out to lunch past a certain margin.  It can reboot the system
-	  or merely print a warning.
-
-source "drivers/char/watchdog/Kconfig"
-
-comment "S/390 character device drivers"
-
-config TN3270
-	tristate "Support for locally attached 3270 terminals"
-	help
-	  Include support for IBM 3270 terminals.
-
-config TN3270_TTY
-	tristate "Support for tty input/output on 3270 terminals"
-	depends on TN3270
-	help
-	  Include support for using an IBM 3270 terminal as a Linux tty.
-
-config TN3270_FS
-	tristate "Support for fullscreen applications on 3270 terminals"
-	depends on TN3270
-	help
-	  Include support for fullscreen applications on an IBM 3270 terminal.
-
-config TN3270_CONSOLE
-	bool "Support for console on 3270 terminal"
-	depends on TN3270=y && TN3270_TTY=y
-	help
-	  Include support for using an IBM 3270 terminal as a Linux system
-	  console.  Available only if 3270 support is compiled in statically.
-
-config TN3215
-	bool "Support for 3215 line mode terminal"
-	help
-	  Include support for IBM 3215 line-mode terminals.
-
-config TN3215_CONSOLE
-	bool "Support for console on 3215 line mode terminal"
-	depends on TN3215
-	help
-	  Include support for using an IBM 3215 line-mode terminal as a
-	  Linux system console.
-
-config CCW_CONSOLE
- 	bool
- 	depends on TN3215_CONSOLE || TN3270_CONSOLE
- 	default y
- 
-config SCLP_TTY
-	bool "Support for SCLP line mode terminal"
-	help
-	  Include support for IBM SCLP line-mode terminals.
-
-config SCLP_CONSOLE
-	bool "Support for console on SCLP line mode terminal"
-	depends on SCLP_TTY
-	help
-	  Include support for using an IBM HWC line-mode terminal as the Linux
-	  system console.
-
-config SCLP_VT220_TTY
-	bool "Support for SCLP VT220-compatible terminal"
-	help
-	  Include support for an IBM SCLP VT220-compatible terminal.
-
-config SCLP_VT220_CONSOLE
-	bool "Support for console on SCLP VT220-compatible terminal"
-	depends on SCLP_VT220_TTY
-	help
-	  Include support for using an IBM SCLP VT220-compatible terminal as a
-	  Linux system console.
-
-config SCLP_CPI
-	tristate "Control-Program Identification"
-	help
-	  This option enables the hardware console interface for system
-	  identification. This is commonly used for workload management and
-	  gives you a nice name for the system on the service element.
-	  Please select this option as a module since built-in operation is
-	  completely untested.
-	  You should only select this option if you know what you are doing,
-	  need this feature and intend to run your kernel in LPAR.
-
-config S390_TAPE
-	tristate "S/390 tape device support"
-	help
-	  Select this option if you want to access channel-attached tape
-	  devices on IBM S/390 or zSeries.
-	  If you select this option you will also want to select at
-	  least one of the tape interface options and one of the tape
-	  hardware options in order to access a tape device.
-	  This option is also available as a module. The module will be
-	  called tape390 and include all selected interfaces and
-	  hardware drivers.
-
-comment "S/390 tape interface support"
-	depends on S390_TAPE
-
-config S390_TAPE_BLOCK
-	bool "Support for tape block devices"
-	depends on S390_TAPE
-	help
-	  Select this option if you want to access your channel-attached tape
-	  devices using the block device interface.  This interface is similar
-	  to CD-ROM devices on other platforms.  The tapes can only be
-	  accessed read-only when using this interface.  Have a look at
-	  <file:Documentation/s390/TAPE> for further information about creating
-	  volumes for and using this interface.  It is safe to say "Y" here.
-
-comment "S/390 tape hardware support"
-	depends on S390_TAPE
-
-config S390_TAPE_34XX
-	tristate "Support for 3480/3490 tape hardware"
-	depends on S390_TAPE
-	help
-	  Select this option if you want to access IBM 3480/3490 magnetic
-	  tape subsystems and 100% compatibles.
-	  It is safe to say "Y" here.
-
-config S390_TAPE_3590
-	tristate "Support for 3590 tape hardware"
-	depends on S390_TAPE
-	help
-	  Select this option if you want to access IBM 3590 magnetic
-	  tape subsystems and 100% compatibles.
-	  It is safe to say "Y" here.
-
-config VMLOGRDR
-	tristate "Support for the z/VM recording system services (VM only)"
-	depends on IUCV
-	help
-	  Select this option if you want to be able to receive records collected
-	  by the z/VM recording system services, eg. from *LOGREC, *ACCOUNT or
-	  *SYMPTOM.
-	  This driver depends on the IUCV support driver.
-
-config VMCP
-	tristate "Support for the z/VM CP interface (VM only)"
-	help
-	  Select this option if you want to be able to interact with the control
-	  program on z/VM
-
-
-config MONREADER
-	tristate "API for reading z/VM monitor service records"
-	depends on IUCV
-	help
-	  Character device driver for reading z/VM monitor service records
-
-config MONWRITER
-	tristate "API for writing z/VM monitor service records"
-	default "m"
-	help
-	  Character device driver for writing z/VM monitor service records
-
-endmenu
-
-menu "Cryptographic devices"
-
-config ZCRYPT
-	tristate "Support for PCI-attached cryptographic adapters"
-	select ZCRYPT_MONOLITHIC if ZCRYPT="y"
-	default "m"
-	help
-	  Select this option if you want to use a PCI-attached cryptographic
-	  adapter like:
-	  + PCI Cryptographic Accelerator (PCICA)
-	  + PCI Cryptographic Coprocessor (PCICC)
-	  + PCI-X Cryptographic Coprocessor (PCIXCC)
-	  + Crypto Express2 Coprocessor (CEX2C)
-	  + Crypto Express2 Accelerator (CEX2A)
-
-config ZCRYPT_MONOLITHIC
-	bool "Monolithic zcrypt module"
-	depends on ZCRYPT="m"
-	help
-	  Select this option if you want to have a single module z90crypt.ko
-	  that contains all parts of the crypto device driver (ap bus,
-	  request router and all the card drivers).
-
-endmenu
diff --git a/drivers/s390/block/Kconfig b/drivers/s390/block/Kconfig
index b250c53..e879b21 100644
--- a/drivers/s390/block/Kconfig
+++ b/drivers/s390/block/Kconfig
@@ -1,11 +1,9 @@
-if S390 && BLOCK
-
 comment "S/390 block device drivers"
-	depends on S390
+	depends on S390 && BLOCK
 
 config BLK_DEV_XPRAM
 	tristate "XPRAM disk support"
-	depends on S390
+	depends on S390 && BLOCK
 	help
 	  Select this option if you want to use your expanded storage on S/390
 	  or zSeries as a disk.  This is useful as a _fast_ swap device if you
@@ -15,12 +13,13 @@
 
 config DCSSBLK
 	tristate "DCSSBLK support"
+	depends on S390 && BLOCK
 	help
 	  Support for dcss block device
 
 config DASD
 	tristate "Support for DASD devices"
-	depends on CCW
+	depends on CCW && BLOCK
 	help
 	  Enable this option if you want to access DASDs directly utilizing
 	  S/390s channel subsystem commands. This is necessary for running
@@ -62,5 +61,3 @@
 	  This driver provides a character device interface to the
 	  DASD extended error reporting. This is only needed if you want to
 	  use applications written for the EER facility.
-
-endif
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 9775210..bfeca57 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2174,9 +2174,10 @@
 	return ret;
 }
 
-struct dasd_ccw_req * dasd_generic_build_rdc(struct dasd_device *device,
-					     void *rdc_buffer,
-					     int rdc_buffer_size, char *magic)
+static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
+						   void *rdc_buffer,
+						   int rdc_buffer_size,
+						   char *magic)
 {
 	struct dasd_ccw_req *cqr;
 	struct ccw1 *ccw;
@@ -2219,6 +2220,7 @@
 	dasd_sfree_request(cqr, cqr->device);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(dasd_generic_read_dev_chars);
 
 static int __init
 dasd_init(void)
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index e810e4a..eccac1c 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -50,6 +50,7 @@
 	struct dasd_diag_rw_io iob;
 	struct dasd_diag_init_io iib;
 	blocknum_t pt_block;
+	struct ccw_dev_id dev_id;
 };
 
 struct dasd_diag_req {
@@ -102,7 +103,7 @@
 	iib = &private->iib;
 	memset(iib, 0, sizeof (struct dasd_diag_init_io));
 
-	iib->dev_nr = _ccw_device_get_device_number(device->cdev);
+	iib->dev_nr = private->dev_id.devno;
 	iib->block_size = blocksize;
 	iib->offset = offset;
 	iib->flaga = DASD_DIAG_FLAGA_DEFAULT;
@@ -127,7 +128,7 @@
 	private = (struct dasd_diag_private *) device->private;
 	iib = &private->iib;
 	memset(iib, 0, sizeof (struct dasd_diag_init_io));
-	iib->dev_nr = _ccw_device_get_device_number(device->cdev);
+	iib->dev_nr = private->dev_id.devno;
 	rc = dia250(iib, TERM_BIO);
 	return rc;
 }
@@ -166,7 +167,7 @@
 	private = (struct dasd_diag_private *) device->private;
 	dreq = (struct dasd_diag_req *) cqr->data;
 
-	private->iob.dev_nr = _ccw_device_get_device_number(device->cdev);
+	private->iob.dev_nr = private->dev_id.devno;
 	private->iob.key = 0;
 	private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
 	private->iob.block_count = dreq->block_count;
@@ -323,11 +324,12 @@
 				"memory allocation failed for private data");
 			return -ENOMEM;
 		}
+		ccw_device_get_id(device->cdev, &private->dev_id);
 		device->private = (void *) private;
 	}
 	/* Read Device Characteristics */
 	rdc_data = (void *) &(private->rdc_data);
-	rdc_data->dev_nr = _ccw_device_get_device_number(device->cdev);
+	rdc_data->dev_nr = private->dev_id.devno;
 	rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics);
 
 	rc = diag210((struct diag210 *) rdc_data);
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index c9583fb..418b4e6 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -450,9 +450,9 @@
 	return 0;
 }
 
-struct dasd_ccw_req * dasd_eckd_build_rcd_lpm(struct dasd_device *device,
-					      void *rcd_buffer,
-					      struct ciw *ciw, __u8 lpm)
+static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device,
+						    void *rcd_buffer,
+						    struct ciw *ciw, __u8 lpm)
 {
 	struct dasd_ccw_req *cqr;
 	struct ccw1 *ccw;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 758cfb5..672eb0a 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -255,6 +255,7 @@
 	unsigned long flags;
 	int rc;
 	struct ccw_device *cdev;
+	struct ccw_dev_id dev_id;
 
 	if (!device->discipline->fill_info)
 		return -EINVAL;
@@ -270,8 +271,9 @@
 	}
 
 	cdev = device->cdev;
+	ccw_device_get_id(cdev, &dev_id);
 
-	dasd_info->devno = _ccw_device_get_device_number(device->cdev);
+	dasd_info->devno = dev_id.devno;
 	dasd_info->schid = _ccw_device_get_subchannel_number(device->cdev);
 	dasd_info->cu_type = cdev->id.cu_type;
 	dasd_info->cu_model = cdev->id.cu_model;
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig
new file mode 100644
index 0000000..66102a1
--- /dev/null
+++ b/drivers/s390/char/Kconfig
@@ -0,0 +1,166 @@
+comment "S/390 character device drivers"
+	depends on S390
+
+config TN3270
+	tristate "Support for locally attached 3270 terminals"
+	depends on CCW
+	help
+	  Include support for IBM 3270 terminals.
+
+config TN3270_TTY
+	tristate "Support for tty input/output on 3270 terminals"
+	depends on TN3270
+	help
+	  Include support for using an IBM 3270 terminal as a Linux tty.
+
+config TN3270_FS
+	tristate "Support for fullscreen applications on 3270 terminals"
+	depends on TN3270
+	help
+	  Include support for fullscreen applications on an IBM 3270 terminal.
+
+config TN3270_CONSOLE
+	bool "Support for console on 3270 terminal"
+	depends on TN3270=y && TN3270_TTY=y
+	help
+	  Include support for using an IBM 3270 terminal as a Linux system
+	  console.  Available only if 3270 support is compiled in statically.
+
+config TN3215
+	bool "Support for 3215 line mode terminal"
+	depends on CCW
+	help
+	  Include support for IBM 3215 line-mode terminals.
+
+config TN3215_CONSOLE
+	bool "Support for console on 3215 line mode terminal"
+	depends on TN3215
+	help
+	  Include support for using an IBM 3215 line-mode terminal as a
+	  Linux system console.
+
+config CCW_CONSOLE
+	bool
+	depends on TN3215_CONSOLE || TN3270_CONSOLE
+	default y
+
+config SCLP
+	bool "Support for SCLP"
+	depends on S390
+	help
+	  Include support for the SCLP interface to the service element.
+
+config SCLP_TTY
+	bool "Support for SCLP line mode terminal"
+	depends on SCLP
+	help
+	  Include support for IBM SCLP line-mode terminals.
+
+config SCLP_CONSOLE
+	bool "Support for console on SCLP line mode terminal"
+	depends on SCLP_TTY
+	help
+	  Include support for using an IBM HWC line-mode terminal as the Linux
+	  system console.
+
+config SCLP_VT220_TTY
+	bool "Support for SCLP VT220-compatible terminal"
+	depends on SCLP
+	help
+	  Include support for an IBM SCLP VT220-compatible terminal.
+
+config SCLP_VT220_CONSOLE
+	bool "Support for console on SCLP VT220-compatible terminal"
+	depends on SCLP_VT220_TTY
+	help
+	  Include support for using an IBM SCLP VT220-compatible terminal as a
+	  Linux system console.
+
+config SCLP_CPI
+	tristate "Control-Program Identification"
+	depends on SCLP
+	help
+	  This option enables the hardware console interface for system
+	  identification. This is commonly used for workload management and
+	  gives you a nice name for the system on the service element.
+	  Please select this option as a module since built-in operation is
+	  completely untested.
+	  You should only select this option if you know what you are doing,
+	  need this feature and intend to run your kernel in LPAR.
+
+config S390_TAPE
+	tristate "S/390 tape device support"
+	depends on CCW
+	help
+	  Select this option if you want to access channel-attached tape
+	  devices on IBM S/390 or zSeries.
+	  If you select this option you will also want to select at
+	  least one of the tape interface options and one of the tape
+	  hardware options in order to access a tape device.
+	  This option is also available as a module. The module will be
+	  called tape390 and include all selected interfaces and
+	  hardware drivers.
+
+comment "S/390 tape interface support"
+	depends on S390_TAPE
+
+config S390_TAPE_BLOCK
+	bool "Support for tape block devices"
+	depends on S390_TAPE
+	help
+	  Select this option if you want to access your channel-attached tape
+	  devices using the block device interface.  This interface is similar
+	  to CD-ROM devices on other platforms.  The tapes can only be
+	  accessed read-only when using this interface.  Have a look at
+	  <file:Documentation/s390/TAPE> for further information about creating
+	  volumes for and using this interface.  It is safe to say "Y" here.
+
+comment "S/390 tape hardware support"
+	depends on S390_TAPE
+
+config S390_TAPE_34XX
+	tristate "Support for 3480/3490 tape hardware"
+	depends on S390_TAPE
+	help
+	  Select this option if you want to access IBM 3480/3490 magnetic
+	  tape subsystems and 100% compatibles.
+	  It is safe to say "Y" here.
+
+config S390_TAPE_3590
+	tristate "Support for 3590 tape hardware"
+	depends on S390_TAPE
+	help
+	  Select this option if you want to access IBM 3590 magnetic
+	  tape subsystems and 100% compatibles.
+	  It is safe to say "Y" here.
+
+config VMLOGRDR
+	tristate "Support for the z/VM recording system services (VM only)"
+	depends on IUCV
+	help
+	  Select this option if you want to be able to receive records collected
+	  by the z/VM recording system services, eg. from *LOGREC, *ACCOUNT or
+	  *SYMPTOM.
+	  This driver depends on the IUCV support driver.
+
+config VMCP
+	tristate "Support for the z/VM CP interface (VM only)"
+	depends on S390
+	help
+	  Select this option if you want to be able to interact with the control
+	  program on z/VM
+
+
+config MONREADER
+	tristate "API for reading z/VM monitor service records"
+	depends on IUCV
+	help
+	  Character device driver for reading z/VM monitor service records
+
+config MONWRITER
+	tristate "API for writing z/VM monitor service records"
+	depends on S390
+	default "m"
+	help
+	  Character device driver for writing z/VM monitor service records
+
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 8df7b13..67009bf 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -97,7 +97,7 @@
  * Create the 8 bytes EBCDIC DCSS segment name from
  * an ASCII name, incl. padding
  */
-static inline void dcss_mkname(char *ascii_name, char *ebcdic_name)
+static void dcss_mkname(char *ascii_name, char *ebcdic_name)
 {
 	int i;
 
@@ -191,7 +191,7 @@
 	return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8));
 }
 
-static inline int mon_check_mca(struct mon_msg *monmsg)
+static int mon_check_mca(struct mon_msg *monmsg)
 {
 	if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) ||
 	    (mon_rec_start(monmsg) < mon_dcss_start) ||
@@ -209,8 +209,8 @@
 	return 0;
 }
 
-static inline int mon_send_reply(struct mon_msg *monmsg,
-				 struct mon_private *monpriv)
+static int mon_send_reply(struct mon_msg *monmsg,
+			  struct mon_private *monpriv)
 {
 	int rc;
 
@@ -236,7 +236,7 @@
 	return 0;
 }
 
-static inline void mon_free_mem(struct mon_private *monpriv)
+static void mon_free_mem(struct mon_private *monpriv)
 {
 	int i;
 
@@ -246,7 +246,7 @@
 	kfree(monpriv);
 }
 
-static inline struct mon_private *mon_alloc_mem(void)
+static struct mon_private *mon_alloc_mem(void)
 {
 	int i;
 	struct mon_private *monpriv;
@@ -307,7 +307,7 @@
 	monmsg->pos = 0;
 }
 
-static inline struct mon_msg *mon_next_message(struct mon_private *monpriv)
+static struct mon_msg *mon_next_message(struct mon_private *monpriv)
 {
 	struct mon_msg *monmsg;
 
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 8facd14..f6ef90e 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -589,9 +589,10 @@
 __raw3270_size_device_vm(struct raw3270 *rp)
 {
 	int rc, model;
+	struct ccw_dev_id dev_id;
 
-	raw3270_init_diag210.vrdcdvno = 
-		_ccw_device_get_device_number(rp->cdev);
+	ccw_device_get_id(rp->cdev, &dev_id);
+	raw3270_init_diag210.vrdcdvno = dev_id.devno;
 	raw3270_init_diag210.vrdclen = sizeof(struct diag210);
 	rc = diag210(&raw3270_init_diag210);
 	if (rc)
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index 87ac4a3..dbb99d1 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -132,6 +132,9 @@
 int sclp_reactivate(void);
 int sclp_service_call(sclp_cmdw_t command, void *sccb);
 
+int sclp_sdias_init(void);
+void sclp_sdias_exit(void);
+
 /* useful inlines */
 
 /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c
index 52283da..1c06497 100644
--- a/drivers/s390/char/sclp_sdias.c
+++ b/drivers/s390/char/sclp_sdias.c
@@ -66,9 +66,9 @@
 
 static void sdias_callback(struct sclp_req *request, void *data)
 {
-	struct sdias_sccb *sccb;
+	struct sdias_sccb *cbsccb;
 
-	sccb = (struct sdias_sccb *) request->sccb;
+	cbsccb = (struct sdias_sccb *) request->sccb;
 	sclp_req_done = 1;
 	wake_up(&sdias_wq); /* Inform caller, that request is complete */
 	TRACE("callback done\n");
@@ -229,7 +229,7 @@
 	return rc;
 }
 
-int __init sdias_init(void)
+int __init sclp_sdias_init(void)
 {
 	int rc;
 
@@ -248,7 +248,7 @@
 	return 0;
 }
 
-void __exit sdias_exit(void)
+void __exit sclp_sdias_exit(void)
 {
 	debug_unregister(sdias_dbf);
 	sclp_unregister(&sclp_sdias_register);
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 89d43931..66eb068 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -21,6 +21,7 @@
 #include <asm/debug.h>
 #include <asm/processor.h>
 #include <asm/irqflags.h>
+#include "sclp.h"
 
 #define TRACE(x...) debug_sprintf_event(zcore_dbf, 1, x)
 #define MSG(x...) printk( KERN_ALERT x )
@@ -564,8 +565,6 @@
 	get_cpu_id(&hdr->cpu_id);
 }
 
-extern int sdias_init(void);
-
 static int __init zcore_init(void)
 {
 	unsigned char arch;
@@ -582,7 +581,7 @@
 	TRACE("wwpn:   %llx\n", (unsigned long long) ipl_info.data.fcp.wwpn);
 	TRACE("lun:    %llx\n", (unsigned long long) ipl_info.data.fcp.lun);
 
-	rc = sdias_init();
+	rc = sclp_sdias_init();
 	if (rc)
 		goto fail;
 
@@ -634,12 +633,10 @@
 	return rc;
 }
 
-extern void sdias_exit(void);
-
 static void __exit zcore_exit(void)
 {
 	debug_unregister(zcore_dbf);
-	sdias_exit();
+	sclp_sdias_exit();
 	diag308(DIAG308_REL_HSA, NULL);
 }
 
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 27c6d9e..dfca0ef 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -191,8 +191,7 @@
 	return ret;
 }
 
-int
-css_probe_device(struct subchannel_id schid)
+static int css_probe_device(struct subchannel_id schid)
 {
 	int ret;
 	struct subchannel *sch;
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index 71fcfdc..ed79775 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -138,9 +138,7 @@
  * all css_drivers have the css_bus_type
  */
 extern struct bus_type css_bus_type;
-extern struct css_driver io_subchannel_driver;
 
-extern int css_probe_device(struct subchannel_id);
 extern int css_sch_device_register(struct subchannel *);
 extern void css_sch_device_unregister(struct subchannel *);
 extern struct subchannel * get_subchannel_by_schid(struct subchannel_id);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index a23ff58..a8b373f 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -129,7 +129,7 @@
 static void io_subchannel_ioterm(struct device *);
 static void io_subchannel_shutdown(struct subchannel *);
 
-struct css_driver io_subchannel_driver = {
+static struct css_driver io_subchannel_driver = {
 	.subchannel_type = SUBCHANNEL_TYPE_IO,
 	.drv = {
 		.name = "io_subchannel",
@@ -546,7 +546,7 @@
 	.attrs = ccwdev_attrs,
 };
 
-struct attribute_group *ccwdev_attr_groups[] = {
+static struct attribute_group *ccwdev_attr_groups[] = {
 	&ccwdev_attr_group,
 	NULL,
 };
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 16f59fc..a5d263f 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -616,6 +616,17 @@
 	return chp_get_chp_desc(chpid);
 }
 
+/**
+ * ccw_device_get_id - obtain a ccw device id
+ * @cdev: device to obtain the id for
+ * @dev_id: where to fill in the values
+ */
+void ccw_device_get_id(struct ccw_device *cdev, struct ccw_dev_id *dev_id)
+{
+	*dev_id = cdev->private->dev_id;
+}
+EXPORT_SYMBOL(ccw_device_get_id);
+
 // FIXME: these have to go:
 
 int
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index f770018..e70aeb7 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -1983,6 +1983,7 @@
 		if (q->is_input_q&QDIO_FLAG_NO_INPUT_INTERRUPT_CONTEXT)
 			qdio_mark_q(q);
 		else {
+			qdio_perf_stat_dec(&perf_stats.tl_runs);
 			__qdio_inbound_processing(q);
 		}
 	}
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index f98fa46..eada69d 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -3,7 +3,7 @@
 
 config LCS
 	tristate "Lan Channel Station Interface"
-	depends on NETDEVICES && (NET_ETHERNET || TR || FDDI)
+	depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
 	help
 	   Select this option if you want to use LCS networking  on IBM S/390
   	   or zSeries. This device driver supports Token Ring (IEEE 802.5),
@@ -13,7 +13,7 @@
 
 config CTC
 	tristate "CTC device support"
-	depends on NETDEVICES
+	depends on CCW && NETDEVICES
 	help
 	  Select this option if you want to use channel-to-channel networking
 	  on IBM S/390 or zSeries. This device driver supports real CTC
@@ -42,7 +42,7 @@
 
 config CLAW
 	tristate "CLAW device support"
-	depends on NETDEVICES
+	depends on CCW && NETDEVICES
 	help
 	  This driver supports channel attached CLAW devices.
 	  CLAW is Common Link Access for Workstation.  Common devices
@@ -52,7 +52,7 @@
 
 config QETH
 	tristate "Gigabit Ethernet device support"
-	depends on NETDEVICES && IP_MULTICAST && QDIO
+	depends on CCW && NETDEVICES && IP_MULTICAST && QDIO
 	help
 	  This driver supports the IBM S/390 and zSeries OSA Express adapters
 	  in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN
diff --git a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c
index f54fdfd..f29a4bc 100644
--- a/drivers/s390/net/qeth_mpc.c
+++ b/drivers/s390/net/qeth_mpc.c
@@ -162,7 +162,7 @@
 	char *msg;
 };
 
-struct ipa_rc_msg qeth_ipa_rc_msg[] = {
+static struct ipa_rc_msg qeth_ipa_rc_msg[] = {
 	{IPA_RC_SUCCESS,		"success"},
 	{IPA_RC_NOTSUPP,		"Command not supported"},
 	{IPA_RC_IP_TABLE_FULL,		"Add Addr IP Table Full - ipv6"},
@@ -226,7 +226,7 @@
 	char *name;
 };
 
-struct ipa_cmd_names qeth_ipa_cmd_names[] = {
+static struct ipa_cmd_names qeth_ipa_cmd_names[] = {
 	{IPA_CMD_STARTLAN,	"startlan"},
 	{IPA_CMD_STOPLAN,	"stoplan"},
 	{IPA_CMD_SETVMAC,	"setvmac"},
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 324899c..ddff40c 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -607,8 +607,7 @@
  * @sg_count: elements in array
  * Return: size of entire scatter-gather list
  */
-size_t
-zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
+static size_t zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
 {
 	unsigned int i;
 	struct scatterlist *p;
@@ -975,8 +974,7 @@
 		mempool_destroy(adapter->pool.data_gid_pn);
 }
 
-void
-zfcp_dummy_release(struct device *dev)
+static void zfcp_dummy_release(struct device *dev)
 {
 	return;
 }
@@ -1336,7 +1334,7 @@
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_FC
 
-void
+static void
 zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
 			   struct fsf_status_read_buffer *status_buffer)
 {
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index d8191d1..5f32124 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -478,7 +478,7 @@
 	NULL
 };
 
-void
+static void
 _zfcp_san_dbf_event_common_ct(const char *tag, struct zfcp_fsf_req *fsf_req,
 			      u32 s_id, u32 d_id, void *buffer, int buflen)
 {
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index a15752b..eef8275 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -6,87 +6,49 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu)
  * Copyright (C) 2001 Florian Lohoff (flo@rfc822.org)
- * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2003, 07 Ralf Baechle (ralf@linux-mips.org)
  * 
  * (In all truth, Jed Schimmel wrote all this code.)
  */
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
+
+#undef DEBUG
+
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 #include <linux/spinlock.h>
 
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/sgialib.h>
-#include <asm/sgi/sgi.h>
-#include <asm/sgi/mc.h>
 #include <asm/sgi/hpc3.h>
 #include <asm/sgi/ip22.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <asm/sgi/wd.h>
 
 #include "scsi.h"
-#include <scsi/scsi_host.h>
 #include "wd33c93.h"
 
-#include <linux/stat.h>
-
-#if 0
-#define DPRINTK(args...)	printk(args)
-#else
-#define DPRINTK(args...)
-#endif
-
-#define HDATA(ptr) ((struct ip22_hostdata *)((ptr)->hostdata))
-
 struct ip22_hostdata {
 	struct WD33C93_hostdata wh;
 	struct hpc_data {
 		dma_addr_t      dma;
-		void            * cpu;
+		void		*cpu;
 	} hd;
 };
 
+#define host_to_hostdata(host) ((struct ip22_hostdata *)((host)->hostdata))
+
 struct hpc_chunk {
 	struct hpc_dma_desc desc;
 	u32 _padding;	/* align to quadword boundary */
 };
 
-struct Scsi_Host *sgiwd93_host;
-struct Scsi_Host *sgiwd93_host1;
-
-/* Wuff wuff, wuff, wd33c93.c, wuff wuff, object oriented, bow wow. */
-static inline void write_wd33c93_count(const wd33c93_regs regs,
-                                      unsigned long value)
-{
-	*regs.SASR = WD_TRANSFER_COUNT_MSB;
-	mb();
-	*regs.SCMD = ((value >> 16) & 0xff);
-	*regs.SCMD = ((value >>  8) & 0xff);
-	*regs.SCMD = ((value >>  0) & 0xff);
-	mb();
-}
-
-static inline unsigned long read_wd33c93_count(const wd33c93_regs regs)
-{
-	unsigned long value;
-
-	*regs.SASR = WD_TRANSFER_COUNT_MSB;
-	mb();
-	value =  ((*regs.SCMD & 0xff) << 16);
-	value |= ((*regs.SCMD & 0xff) <<  8);
-	value |= ((*regs.SCMD & 0xff) <<  0);
-	mb();
-	return value;
-}
-
 static irqreturn_t sgiwd93_intr(int irq, void *dev_id)
 {
-	struct Scsi_Host * host = (struct Scsi_Host *) dev_id;
+	struct Scsi_Host * host = dev_id;
 	unsigned long flags;
 
 	spin_lock_irqsave(host->host_lock, flags);
@@ -131,12 +93,12 @@
 
 static int dma_setup(struct scsi_cmnd *cmd, int datainp)
 {
-	struct ip22_hostdata *hdata = HDATA(cmd->device->host);
+	struct ip22_hostdata *hdata = host_to_hostdata(cmd->device->host);
 	struct hpc3_scsiregs *hregs =
 		(struct hpc3_scsiregs *) cmd->device->host->base;
 	struct hpc_chunk *hcp = (struct hpc_chunk *) hdata->hd.cpu;
 
-	DPRINTK("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp);
+	pr_debug("dma_setup: datainp<%d> hcp<%p> ", datainp, hcp);
 
 	hdata->wh.dma_dir = datainp;
 
@@ -151,7 +113,7 @@
 
 	fill_hpc_entries(hcp, cmd, datainp);
 
-	DPRINTK(" HPCGO\n");
+	pr_debug(" HPCGO\n");
 
 	/* Start up the HPC. */
 	hregs->ndptr = hdata->hd.dma;
@@ -166,7 +128,7 @@
 static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
 		     int status)
 {
-	struct ip22_hostdata *hdata = HDATA(instance);
+	struct ip22_hostdata *hdata = host_to_hostdata(instance);
 	struct hpc3_scsiregs *hregs;
 
 	if (!SCpnt)
@@ -174,7 +136,7 @@
 
 	hregs = (struct hpc3_scsiregs *) SCpnt->device->host->base;
 
-	DPRINTK("dma_stop: status<%d> ", status);
+	pr_debug("dma_stop: status<%d> ", status);
 
 	/* First stop the HPC and flush it's FIFO. */
 	if (hdata->wh.dma_dir) {
@@ -186,7 +148,7 @@
 	dma_unmap_single(NULL, SCpnt->SCp.dma_handle, SCpnt->SCp.this_residual,
 	                 SCpnt->sc_data_direction);
 
-	DPRINTK("\n");
+	pr_debug("\n");
 }
 
 void sgiwd93_reset(unsigned long base)
@@ -216,96 +178,6 @@
 	hcp->desc.pnext = hd->dma;
 }
 
-static struct Scsi_Host * __init sgiwd93_setup_scsi(
-	struct scsi_host_template *SGIblows, int unit, int irq,
-	struct hpc3_scsiregs *hregs, unsigned char *wdregs)
-{
-	struct ip22_hostdata *hdata;
-	struct Scsi_Host *host;
-	wd33c93_regs regs;
-
-	host = scsi_register(SGIblows, sizeof(struct ip22_hostdata));
-	if (!host)
-		return NULL;
-
-	host->base = (unsigned long) hregs;
-	host->irq = irq;
-
-	hdata = HDATA(host);
-	hdata->hd.cpu = dma_alloc_coherent(NULL, PAGE_SIZE, &hdata->hd.dma,
-	                                   GFP_KERNEL);
-	if (!hdata->hd.cpu) {
-		printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
-		       "host %d buffer.\n", unit);
-		goto out_unregister;
-	}
-	init_hpc_chain(&hdata->hd);
-
-	regs.SASR = wdregs + 3;
-	regs.SCMD = wdregs + 7;
-
-	wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
-
-	if (hdata->wh.no_sync == 0xff)
-		hdata->wh.no_sync = 0;
-
-	if (request_irq(irq, sgiwd93_intr, 0, "SGI WD93", (void *) host)) {
-		printk(KERN_WARNING "sgiwd93: Could not register irq %d "
-		       "for host %d.\n", irq, unit);
-		goto out_free;
-	}
-	return host;
-
-out_free:
-	dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
-	wd33c93_release();
-
-out_unregister:
-	scsi_unregister(host);
-
-	return NULL;
-}
-
-static int __init sgiwd93_detect(struct scsi_host_template *SGIblows)
-{
-	int found = 0;
-
-	SGIblows->proc_name = "SGIWD93";
-	sgiwd93_host = sgiwd93_setup_scsi(SGIblows, 0, SGI_WD93_0_IRQ,
-	                                  &hpc3c0->scsi_chan0,
-	                                  (unsigned char *)hpc3c0->scsi0_ext);
-	if (sgiwd93_host)
-		found++;
-
-	/* Set up second controller on the Indigo2 */
-	if (ip22_is_fullhouse()) {
-		sgiwd93_host1 = sgiwd93_setup_scsi(SGIblows, 1, SGI_WD93_1_IRQ,
-		                          &hpc3c0->scsi_chan1,
-		                          (unsigned char *)hpc3c0->scsi1_ext);
-		if (sgiwd93_host1)
-			found++;
-	}
-
-	return found;
-}
-
-static int sgiwd93_release(struct Scsi_Host *instance)
-{
-	struct ip22_hostdata *hdata = HDATA(instance);
-	int irq = 0;
-
-	if (sgiwd93_host && sgiwd93_host == instance)
-		irq = SGI_WD93_0_IRQ;
-	else if (sgiwd93_host1 && sgiwd93_host1 == instance)
-		irq = SGI_WD93_1_IRQ;
-
-	free_irq(irq, sgiwd93_intr);
-	dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
-	wd33c93_release();
-
-	return 1;
-}
-
 static int sgiwd93_bus_reset(struct scsi_cmnd *cmd)
 {
 	/* FIXME perform bus-specific reset */
@@ -325,11 +197,10 @@
  * arguments not with pointers.  So this is going to blow up beautyfully
  * on 64-bit systems with memory outside the compat address spaces.
  */
-static struct scsi_host_template driver_template = {
+static struct scsi_host_template sgiwd93_template = {
+	.module			= THIS_MODULE,
 	.proc_name		= "SGIWD93",
 	.name			= "SGI WD93",
-	.detect			= sgiwd93_detect,
-	.release		= sgiwd93_release,
 	.queuecommand		= wd33c93_queuecommand,
 	.eh_abort_handler	= wd33c93_abort,
 	.eh_bus_reset_handler	= sgiwd93_bus_reset,
@@ -340,4 +211,109 @@
 	.cmd_per_lun		= 8,
 	.use_clustering		= DISABLE_CLUSTERING,
 };
-#include "scsi_module.c"
+
+static int __init sgiwd93_probe(struct platform_device *pdev)
+{
+	struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
+	unsigned char *wdregs = pd->wdregs;
+	struct hpc3_scsiregs *hregs = pd->hregs;
+	struct ip22_hostdata *hdata;
+	struct Scsi_Host *host;
+	wd33c93_regs regs;
+	unsigned int unit = pd->unit;
+	unsigned int irq = pd->irq;
+	int err;
+
+	host = scsi_host_alloc(&sgiwd93_template, sizeof(struct ip22_hostdata));
+	if (!host) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	host->base = (unsigned long) hregs;
+	host->irq = irq;
+
+	hdata = host_to_hostdata(host);
+	hdata->hd.cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,
+	                                   &hdata->hd.dma, GFP_KERNEL);
+	if (!hdata->hd.cpu) {
+		printk(KERN_WARNING "sgiwd93: Could not allocate memory for "
+		       "host %d buffer.\n", unit);
+		err = -ENOMEM;
+		goto out_put;
+	}
+
+	init_hpc_chain(&hdata->hd);
+
+	regs.SASR = wdregs + 3;
+	regs.SCMD = wdregs + 7;
+
+	wd33c93_init(host, regs, dma_setup, dma_stop, WD33C93_FS_MHZ(20));
+
+	if (hdata->wh.no_sync == 0xff)
+		hdata->wh.no_sync = 0;
+
+	err = request_irq(irq, sgiwd93_intr, 0, "SGI WD93", host);
+	if (err) {
+		printk(KERN_WARNING "sgiwd93: Could not register irq %d "
+		       "for host %d.\n", irq, unit);
+		goto out_free;
+	}
+
+	platform_set_drvdata(pdev, host);
+
+	err = scsi_add_host(host, NULL);
+	if (err)
+		goto out_irq;
+
+	scsi_scan_host(host);
+
+	return 0;
+
+out_irq:
+	free_irq(irq, host);
+out_free:
+	dma_free_coherent(NULL, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
+out_put:
+	scsi_host_put(host);
+out:
+
+	return err;
+}
+
+static void __exit sgiwd93_remove(struct platform_device *pdev)
+{
+	struct Scsi_Host *host = platform_get_drvdata(pdev);
+	struct ip22_hostdata *hdata = (struct ip22_hostdata *) host->hostdata;
+	struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
+
+	scsi_remove_host(host);
+	free_irq(pd->irq, host);
+	dma_free_coherent(&pdev->dev, PAGE_SIZE, hdata->hd.cpu, hdata->hd.dma);
+	scsi_host_put(host);
+}
+
+static struct platform_driver sgiwd93_driver = {
+	.probe  = sgiwd93_probe,
+	.remove = __devexit_p(sgiwd93_remove),
+	.driver = {
+		.name   = "sgiwd93"
+	}
+};
+
+static int __init sgiwd93_module_init(void)
+{
+	return platform_driver_register(&sgiwd93_driver);
+}
+
+static void __exit sgiwd93_module_exit(void)
+{
+	return platform_driver_unregister(&sgiwd93_driver);
+}
+
+module_init(sgiwd93_module_init);
+module_exit(sgiwd93_module_exit);
+
+MODULE_DESCRIPTION("SGI WD33C93 driver");
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index e8efe93..a6f5bfb 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -5,6 +5,7 @@
 #
 
 menu "Serial drivers"
+	depends on HAS_IOMEM
 
 #
 # The new 8250/16550 serial drivers
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
index 69715e5..a8f894c 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -88,7 +88,7 @@
 
 /* these are located in their respective files */
 void cpm_line_cr_cmd(int line, int cmd);
-int __init cpm_uart_init_portdesc(void);
+int cpm_uart_init_portdesc(void);
 int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
 void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index f23972b..b63ff8d 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -482,7 +482,8 @@
 }
 
 static void cpm_uart_set_termios(struct uart_port *port,
-				 struct termios *termios, struct termios *old)
+                                 struct ktermios *termios,
+                                 struct ktermios *old)
 {
 	int baud;
 	unsigned long flags;
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 925fb60..8c6324e 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -125,7 +125,7 @@
 {
 	int dpmemsz, memsz;
 	u8 *dp_mem;
-	uint dp_offset;
+	unsigned long dp_offset;
 	u8 *mem_addr;
 	dma_addr_t dma_addr = 0;
 
@@ -133,7 +133,7 @@
 
 	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
 	dp_offset = cpm_dpalloc(dpmemsz, 8);
-	if (IS_DPERR(dp_offset)) {
+	if (IS_ERR_VALUE(dp_offset)) {
 		printk(KERN_ERR
 		       "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
 		return -ENOMEM;
@@ -185,7 +185,7 @@
 }
 
 /* Setup any dynamic params in the uart desc */
-int __init cpm_uart_init_portdesc(void)
+int cpm_uart_init_portdesc(void)
 {
 	pr_debug("CPM uart[-]:init portdesc\n");
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index fa45599..7b61d80 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -222,7 +222,7 @@
 {
 	int dpmemsz, memsz;
 	u8 *dp_mem;
-	uint dp_offset;
+	unsigned long dp_offset;
 	u8 *mem_addr;
 	dma_addr_t dma_addr = 0;
 
@@ -230,7 +230,7 @@
 
 	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
 	dp_offset = cpm_dpalloc(dpmemsz, 8);
-	if (IS_DPERR(dp_offset)) {
+	if (IS_ERR_VALUE(dp_offset)) {
 		printk(KERN_ERR
 		       "cpm_uart_cpm.c: could not allocate buffer descriptors\n");
 		return -ENOMEM;
@@ -282,7 +282,7 @@
 }
 
 /* Setup any dynamic params in the uart desc */
-int __init cpm_uart_init_portdesc(void)
+int cpm_uart_init_portdesc(void)
 {
 #if defined(CONFIG_SERIAL_CPM_SMC1) || defined(CONFIG_SERIAL_CPM_SMC2)
 	u16 *addr;
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index da73205..0985193 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -92,6 +92,8 @@
 #define SUNZILOG_FLAG_REGS_HELD		0x00000040
 #define SUNZILOG_FLAG_TX_STOPPED	0x00000080
 #define SUNZILOG_FLAG_TX_ACTIVE		0x00000100
+#define SUNZILOG_FLAG_ESCC		0x00000200
+#define SUNZILOG_FLAG_ISR_HANDLER	0x00000400
 
 	unsigned int cflag;
 
@@ -174,9 +176,11 @@
 /* This function must only be called when the TX is not busy.  The UART
  * port lock must be held and local interrupts disabled.
  */
-static void __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
+static int __load_zsregs(struct zilog_channel __iomem *channel, unsigned char *regs)
 {
 	int i;
+	int escc;
+	unsigned char r15;
 
 	/* Let pending transmits finish.  */
 	for (i = 0; i < 1000; i++) {
@@ -229,11 +233,25 @@
 	write_zsreg(channel, R14, regs[R14]);
 
 	/* External status interrupt control.  */
-	write_zsreg(channel, R15, regs[R15]);
+	write_zsreg(channel, R15, (regs[R15] | WR7pEN) & ~FIFOEN);
+
+	/* ESCC Extension Register */
+	r15 = read_zsreg(channel, R15);
+	if (r15 & 0x01)	{
+		write_zsreg(channel, R7,  regs[R7p]);
+
+		/* External status interrupt and FIFO control.  */
+		write_zsreg(channel, R15, regs[R15] & ~WR7pEN);
+		escc = 1;
+	} else {
+		 /* Clear FIFO bit case it is an issue */
+		regs[R15] &= ~FIFOEN;
+		escc = 0;
+	}
 
 	/* Reset external status interrupts.  */
-	write_zsreg(channel, R0, RES_EXT_INT);
-	write_zsreg(channel, R0, RES_EXT_INT);
+	write_zsreg(channel, R0, RES_EXT_INT); /* First Latch  */
+	write_zsreg(channel, R0, RES_EXT_INT); /* Second Latch */
 
 	/* Rewrite R3/R5, this time without enables masked.  */
 	write_zsreg(channel, R3, regs[R3]);
@@ -241,6 +259,8 @@
 
 	/* Rewrite R1, this time without IRQ enabled masked.  */
 	write_zsreg(channel, R1, regs[R1]);
+
+	return escc;
 }
 
 /* Reprogram the Zilog channel HW registers with the copies found in the
@@ -731,7 +751,7 @@
 		up->curregs[R15] = new_reg;
 
 		/* NOTE: Not subject to 'transmitter active' rule.  */ 
-		write_zsreg(channel, R15, up->curregs[R15]);
+		write_zsreg(channel, R15, up->curregs[R15] & ~WR7pEN);
 	}
 }
 
@@ -861,44 +881,44 @@
 	up->curregs[R14] = BRSRC | BRENAB;
 
 	/* Character size, stop bits, and parity. */
-	up->curregs[3] &= ~RxN_MASK;
-	up->curregs[5] &= ~TxN_MASK;
+	up->curregs[R3] &= ~RxN_MASK;
+	up->curregs[R5] &= ~TxN_MASK;
 	switch (cflag & CSIZE) {
 	case CS5:
-		up->curregs[3] |= Rx5;
-		up->curregs[5] |= Tx5;
+		up->curregs[R3] |= Rx5;
+		up->curregs[R5] |= Tx5;
 		up->parity_mask = 0x1f;
 		break;
 	case CS6:
-		up->curregs[3] |= Rx6;
-		up->curregs[5] |= Tx6;
+		up->curregs[R3] |= Rx6;
+		up->curregs[R5] |= Tx6;
 		up->parity_mask = 0x3f;
 		break;
 	case CS7:
-		up->curregs[3] |= Rx7;
-		up->curregs[5] |= Tx7;
+		up->curregs[R3] |= Rx7;
+		up->curregs[R5] |= Tx7;
 		up->parity_mask = 0x7f;
 		break;
 	case CS8:
 	default:
-		up->curregs[3] |= Rx8;
-		up->curregs[5] |= Tx8;
+		up->curregs[R3] |= Rx8;
+		up->curregs[R5] |= Tx8;
 		up->parity_mask = 0xff;
 		break;
 	};
-	up->curregs[4] &= ~0x0c;
+	up->curregs[R4] &= ~0x0c;
 	if (cflag & CSTOPB)
-		up->curregs[4] |= SB2;
+		up->curregs[R4] |= SB2;
 	else
-		up->curregs[4] |= SB1;
+		up->curregs[R4] |= SB1;
 	if (cflag & PARENB)
-		up->curregs[4] |= PAR_ENAB;
+		up->curregs[R4] |= PAR_ENAB;
 	else
-		up->curregs[4] &= ~PAR_ENAB;
+		up->curregs[R4] &= ~PAR_ENAB;
 	if (!(cflag & PARODD))
-		up->curregs[4] |= PAR_EVEN;
+		up->curregs[R4] |= PAR_EVEN;
 	else
-		up->curregs[4] &= ~PAR_EVEN;
+		up->curregs[R4] &= ~PAR_EVEN;
 
 	up->port.read_status_mask = Rx_OVR;
 	if (iflag & INPCK)
@@ -952,7 +972,9 @@
 
 static const char *sunzilog_type(struct uart_port *port)
 {
-	return "zs";
+	struct uart_sunzilog_port *up = UART_ZILOG(port);
+
+	return (up->flags & SUNZILOG_FLAG_ESCC) ? "zs (ESCC)" : "zs";
 }
 
 /* We do not request/release mappings of the registers here, this
@@ -1170,7 +1192,7 @@
 
 	spin_lock_irqsave(&up->port.lock, flags);
 
-	up->curregs[R15] = BRKIE;
+	up->curregs[R15] |= BRKIE;
 	sunzilog_convert_to_zs(up, con->cflag, 0, brg);
 
 	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
@@ -1229,7 +1251,7 @@
 		baud = 4800;
 	}
 
-	up->curregs[R15] = BRKIE;
+	up->curregs[R15] |= BRKIE;
 	brg = BPS_TO_BRG(baud, ZS_CLOCK / ZS_CLOCK_DIVISOR);
 	sunzilog_convert_to_zs(up, up->cflag, 0, brg);
 	sunzilog_set_mctrl(&up->port, TIOCM_DTR | TIOCM_RTS);
@@ -1283,8 +1305,18 @@
 
 	if (up->flags & (SUNZILOG_FLAG_CONS_KEYB |
 			 SUNZILOG_FLAG_CONS_MOUSE)) {
+		up->curregs[R1] = EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB;
+		up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
+		up->curregs[R3] = RxENAB | Rx8;
+		up->curregs[R5] = TxENAB | Tx8;
+		up->curregs[R6] = 0x00; /* SDLC Address */
+		up->curregs[R7] = 0x7E; /* SDLC Flag    */
+		up->curregs[R9] = NV;
+		up->curregs[R7p] = 0x00;
 		sunzilog_init_kbdms(up, up->port.line);
-		up->curregs[R9] |= (NV | MIE);
+		/* Only enable interrupts if an ISR handler available */
+		if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
+			up->curregs[R9] |= MIE;
 		write_zsreg(channel, R9, up->curregs[R9]);
 	} else {
 		/* Normal serial TTY. */
@@ -1293,7 +1325,9 @@
 		up->curregs[R4] = PAR_EVEN | X16CLK | SB1;
 		up->curregs[R3] = RxENAB | Rx8;
 		up->curregs[R5] = TxENAB | Tx8;
-		up->curregs[R9] = NV | MIE;
+		up->curregs[R6] = 0x00; /* SDLC Address */
+		up->curregs[R7] = 0x7E; /* SDLC Flag    */
+		up->curregs[R9] = NV;
 		up->curregs[R10] = NRZ;
 		up->curregs[R11] = TCBR | RCBR;
 		baud = 9600;
@@ -1301,7 +1335,14 @@
 		up->curregs[R12] = (brg & 0xff);
 		up->curregs[R13] = (brg >> 8) & 0xff;
 		up->curregs[R14] = BRSRC | BRENAB;
-		__load_zsregs(channel, up->curregs);
+		up->curregs[R15] = FIFOEN; /* Use FIFO if on ESCC */
+		up->curregs[R7p] = TxFIFO_LVL | RxFIFO_LVL;
+		if (__load_zsregs(channel, up->curregs)) {
+			up->flags |= SUNZILOG_FLAG_ESCC;
+		}
+		/* Only enable interrupts if an ISR handler available */
+		if (up->flags & SUNZILOG_FLAG_ISR_HANDLER)
+			up->curregs[R9] |= MIE;
 		write_zsreg(channel, R9, up->curregs[R9]);
 	}
 
@@ -1390,12 +1431,14 @@
 			return err;
 		}
 	} else {
-		printk(KERN_INFO "%s: Keyboard at MMIO %lx (irq = %d) "
-		       "is a zs\n",
-		       op->dev.bus_id, up[0].port.mapbase, op->irqs[0]);
-		printk(KERN_INFO "%s: Mouse at MMIO %lx (irq = %d) "
-		       "is a zs\n",
-		       op->dev.bus_id, up[1].port.mapbase, op->irqs[0]);
+		printk(KERN_INFO "%s: Keyboard at MMIO 0x%lx (irq = %d) "
+		       "is a %s\n",
+		       op->dev.bus_id, up[0].port.mapbase, op->irqs[0],
+		       sunzilog_type (&up[0].port));
+		printk(KERN_INFO "%s: Mouse at MMIO 0x%lx (irq = %d) "
+		       "is a %s\n",
+		       op->dev.bus_id, up[1].port.mapbase, op->irqs[0],
+		       sunzilog_type (&up[1].port));
 	}
 
 	dev_set_drvdata(&op->dev, &up[0]);
@@ -1487,10 +1530,23 @@
 		goto out_unregister_uart;
 
 	if (zilog_irq != -1) {
+		struct uart_sunzilog_port *up = sunzilog_irq_chain;
 		err = request_irq(zilog_irq, sunzilog_interrupt, IRQF_SHARED,
 				  "zs", sunzilog_irq_chain);
 		if (err)
 			goto out_unregister_driver;
+
+		/* Enable Interrupts */
+		while (up) {
+			struct zilog_channel __iomem *channel;
+
+			/* printk (KERN_INFO "Enable IRQ for ZILOG Hardware %p\n", up); */
+			channel          = ZILOG_CHANNEL_FROM_PORT(&up->port);
+			up->flags       |= SUNZILOG_FLAG_ISR_HANDLER;
+			up->curregs[R9] |= MIE;
+			write_zsreg(channel, R9, up->curregs[R9]);
+			up = up->next;
+		}
 	}
 
 out:
@@ -1515,6 +1571,20 @@
 	of_unregister_driver(&zs_driver);
 
 	if (zilog_irq != -1) {
+		struct uart_sunzilog_port *up = sunzilog_irq_chain;
+
+		/* Disable Interrupts */
+		while (up) {
+			struct zilog_channel __iomem *channel;
+
+			/* printk (KERN_INFO "Disable IRQ for ZILOG Hardware %p\n", up); */
+			channel          = ZILOG_CHANNEL_FROM_PORT(&up->port);
+			up->flags       &= ~SUNZILOG_FLAG_ISR_HANDLER;
+			up->curregs[R9] &= ~MIE;
+			write_zsreg(channel, R9, up->curregs[R9]);
+			up = up->next;
+		}
+
 		free_irq(zilog_irq, sunzilog_irq_chain);
 		zilog_irq = -1;
 	}
diff --git a/drivers/serial/sunzilog.h b/drivers/serial/sunzilog.h
index 7939b6d..5dec7b4 100644
--- a/drivers/serial/sunzilog.h
+++ b/drivers/serial/sunzilog.h
@@ -13,7 +13,8 @@
 	struct zilog_channel channelA;
 };
 
-#define NUM_ZSREGS    16
+#define	NUM_ZSREGS	17
+#define	R7p		16 /* Written as R7 with P15 bit 0 set */
 
 /* Conversion routines to/from brg time constants from/to bits
  * per second.
@@ -127,6 +128,15 @@
 
 /* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
 
+/* Write Register 7' (ESCC Only) */
+#define	AUTO_TxFLAG	1	/* Automatic Tx SDLC Flag */
+#define	AUTO_EOM_RST	2	/* Automatic EOM Reset */
+#define	AUTOnRTS	4	/* Automatic /RTS pin deactivation */
+#define	RxFIFO_LVL	8	/* Receive FIFO interrupt level */
+#define	nDTRnREQ	0x10	/* /DTR/REQ timing */
+#define	TxFIFO_LVL	0x20	/* Transmit FIFO interrupt level */
+#define	EXT_RD_EN	0x40	/* Extended read register enable */
+
 /* Write Register 8 (transmit buffer) */
 
 /* Write Register 9 (Master interrupt control) */
@@ -135,6 +145,7 @@
 #define	DLC	4	/* Disable Lower Chain */
 #define	MIE	8	/* Master Interrupt Enable */
 #define	STATHI	0x10	/* Status high */
+#define	SWIACK  0x20    /* Software Interrupt Ack (not on NMOS) */
 #define	NORESET	0	/* No reset on write to R9 */
 #define	CHRB	0x40	/* Reset channel B */
 #define	CHRA	0x80	/* Reset channel A */
@@ -187,7 +198,9 @@
 #define	SNRZI	0xe0	/* Set NRZI mode */
 
 /* Write Register 15 (external/status interrupt control) */
+#define	WR7pEN	1	/* WR7' Enable (ESCC only) */
 #define	ZCIE	2	/* Zero count IE */
+#define	FIFOEN	4	/* FIFO Enable (ESCC only) */
 #define	DCDIE	8	/* DCD IE */
 #define	SYNCIE	0x10	/* Sync/hunt IE */
 #define	CTSIE	0x20	/* CTS IE */
@@ -241,6 +254,10 @@
 #define	CHATxIP	0x10		/* Channel A Tx IP */
 #define	CHARxIP	0x20		/* Channel A Rx IP */
 
+/* Read Register 6 (LSB frame byte count [Not on NMOS]) */
+
+/* Read Register 7 (MSB frame byte count and FIFO status [Not on NMOS]) */
+
 /* Read Register 8 (receive data register) */
 
 /* Read Register 10  (misc status bits) */
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 07c587e..5e3f748 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -6,6 +6,7 @@
 # fully appropriate there, so it'd need some thought to do well.
 #
 menu "SPI support"
+	depends on HAS_IOMEM
 
 config SPI
 	bool "SPI support"
@@ -106,6 +107,13 @@
 	  This enables using the Freescale iMX SPI controller in master
 	  mode.
 
+config SPI_MPC52xx_PSC
+	tristate "Freescale MPC52xx PSC SPI controller"
+	depends on SPI_MASTER && PPC_MPC52xx && EXPERIMENTAL
+	help
+	  This enables using the Freescale MPC52xx Programmable Serial
+	  Controller in master SPI mode.
+
 config SPI_MPC83xx
 	tristate "Freescale MPC83xx SPI controller"
 	depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 624b636..5788d86 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
+obj-$(CONFIG_SPI_MPC52xx_PSC)		+= mpc52xx_psc_spi.o
 obj-$(CONFIG_SPI_MPC83xx)		+= spi_mpc83xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)		+= spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx.o
diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
new file mode 100644
index 0000000..052359f
--- /dev/null
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -0,0 +1,654 @@
+/*
+ * MPC52xx SPC in SPI mode driver.
+ *
+ * Maintainer: Dragos Carp
+ *
+ * Copyright (C) 2006 TOPTICA Photonics AG.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+
+#if defined(CONFIG_PPC_MERGE)
+#include <asm/of_platform.h>
+#else
+#include <linux/platform_device.h>
+#endif
+
+#include <linux/workqueue.h>
+#include <linux/completion.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/mpc52xx.h>
+#include <asm/mpc52xx_psc.h>
+
+#define MCLK 20000000 /* PSC port MClk in hz */
+
+struct mpc52xx_psc_spi {
+	/* fsl_spi_platform data */
+	void (*activate_cs)(u8, u8);
+	void (*deactivate_cs)(u8, u8);
+	u32 sysclk;
+
+	/* driver internal data */
+	struct mpc52xx_psc __iomem *psc;
+	unsigned int irq;
+	u8 bits_per_word;
+	u8 busy;
+
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+
+	struct list_head queue;
+	spinlock_t lock;
+
+	struct completion done;
+};
+
+/* controller state */
+struct mpc52xx_psc_spi_cs {
+	int bits_per_word;
+	int speed_hz;
+};
+
+/* set clock freq, clock ramp, bits per work
+ * if t is NULL then reset the values to the default values
+ */
+static int mpc52xx_psc_spi_transfer_setup(struct spi_device *spi,
+		struct spi_transfer *t)
+{
+	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+
+	cs->speed_hz = (t && t->speed_hz)
+			? t->speed_hz : spi->max_speed_hz;
+	cs->bits_per_word = (t && t->bits_per_word)
+			? t->bits_per_word : spi->bits_per_word;
+	cs->bits_per_word = ((cs->bits_per_word + 7) / 8) * 8;
+	return 0;
+}
+
+static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
+{
+	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	u32 sicr;
+	u16 ccr;
+
+	sicr = in_be32(&psc->sicr);
+
+	/* Set clock phase and polarity */
+	if (spi->mode & SPI_CPHA)
+		sicr |= 0x00001000;
+	else
+		sicr &= ~0x00001000;
+	if (spi->mode & SPI_CPOL)
+		sicr |= 0x00002000;
+	else
+		sicr &= ~0x00002000;
+
+	if (spi->mode & SPI_LSB_FIRST)
+		sicr |= 0x10000000;
+	else
+		sicr &= ~0x10000000;
+	out_be32(&psc->sicr, sicr);
+
+	/* Set clock frequency and bits per word
+	 * Because psc->ccr is defined as 16bit register instead of 32bit
+	 * just set the lower byte of BitClkDiv
+	 */
+	ccr = in_be16(&psc->ccr);
+	ccr &= 0xFF00;
+	if (cs->speed_hz)
+		ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
+	else /* by default SPI Clk 1MHz */
+		ccr |= (MCLK / 1000000 - 1) & 0xFF;
+	out_be16(&psc->ccr, ccr);
+	mps->bits_per_word = cs->bits_per_word;
+
+	if (mps->activate_cs)
+		mps->activate_cs(spi->chip_select,
+				(spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+static void mpc52xx_psc_spi_deactivate_cs(struct spi_device *spi)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+
+	if (mps->deactivate_cs)
+		mps->deactivate_cs(spi->chip_select,
+				(spi->mode & SPI_CS_HIGH) ? 1 : 0);
+}
+
+#define MPC52xx_PSC_BUFSIZE (MPC52xx_PSC_RFNUM_MASK + 1)
+/* wake up when 80% fifo full */
+#define MPC52xx_PSC_RFALARM (MPC52xx_PSC_BUFSIZE * 20 / 100)
+
+static int mpc52xx_psc_spi_transfer_rxtx(struct spi_device *spi,
+						struct spi_transfer *t)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	unsigned rb = 0;	/* number of bytes receieved */
+	unsigned sb = 0;	/* number of bytes sent */
+	unsigned char *rx_buf = (unsigned char *)t->rx_buf;
+	unsigned char *tx_buf = (unsigned char *)t->tx_buf;
+	unsigned rfalarm;
+	unsigned send_at_once = MPC52xx_PSC_BUFSIZE;
+	unsigned recv_at_once;
+	unsigned bpw = mps->bits_per_word / 8;
+
+	if (!t->tx_buf && !t->rx_buf && t->len)
+		return -EINVAL;
+
+	/* enable transmiter/receiver */
+	out_8(&psc->command, MPC52xx_PSC_TX_ENABLE | MPC52xx_PSC_RX_ENABLE);
+	while (rb < t->len) {
+		if (t->len - rb > MPC52xx_PSC_BUFSIZE) {
+			rfalarm = MPC52xx_PSC_RFALARM;
+		} else {
+			send_at_once = t->len - sb;
+			rfalarm = MPC52xx_PSC_BUFSIZE - (t->len - rb);
+		}
+
+		dev_dbg(&spi->dev, "send %d bytes...\n", send_at_once);
+		if (tx_buf) {
+			for (; send_at_once; sb++, send_at_once--) {
+				/* set EOF flag */
+				if (mps->bits_per_word
+						&& (sb + 1) % bpw == 0)
+					out_8(&psc->ircr2, 0x01);
+				out_8(&psc->mpc52xx_psc_buffer_8, tx_buf[sb]);
+			}
+		} else {
+			for (; send_at_once; sb++, send_at_once--) {
+				/* set EOF flag */
+				if (mps->bits_per_word
+						&& ((sb + 1) % bpw) == 0)
+					out_8(&psc->ircr2, 0x01);
+				out_8(&psc->mpc52xx_psc_buffer_8, 0);
+			}
+		}
+
+
+		/* enable interupts and wait for wake up
+		 * if just one byte is expected the Rx FIFO genererates no
+		 * FFULL interrupt, so activate the RxRDY interrupt
+		 */
+		out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+		if (t->len - rb == 1) {
+			out_8(&psc->mode, 0);
+		} else {
+			out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
+			out_be16(&psc->rfalarm, rfalarm);
+		}
+		out_be16(&psc->mpc52xx_psc_imr, MPC52xx_PSC_IMR_RXRDY);
+		wait_for_completion(&mps->done);
+		recv_at_once = in_be16(&psc->rfnum);
+		dev_dbg(&spi->dev, "%d bytes received\n", recv_at_once);
+
+		send_at_once = recv_at_once;
+		if (rx_buf) {
+			for (; recv_at_once; rb++, recv_at_once--)
+				rx_buf[rb] = in_8(&psc->mpc52xx_psc_buffer_8);
+		} else {
+			for (; recv_at_once; rb++, recv_at_once--)
+				in_8(&psc->mpc52xx_psc_buffer_8);
+		}
+	}
+	/* disable transmiter/receiver */
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+	return 0;
+}
+
+static void mpc52xx_psc_spi_work(struct work_struct *work)
+{
+	struct mpc52xx_psc_spi *mps =
+		container_of(work, struct mpc52xx_psc_spi, work);
+
+	spin_lock_irq(&mps->lock);
+	mps->busy = 1;
+	while (!list_empty(&mps->queue)) {
+		struct spi_message *m;
+		struct spi_device *spi;
+		struct spi_transfer *t = NULL;
+		unsigned cs_change;
+		int status;
+
+		m = container_of(mps->queue.next, struct spi_message, queue);
+		list_del_init(&m->queue);
+		spin_unlock_irq(&mps->lock);
+
+		spi = m->spi;
+		cs_change = 1;
+		status = 0;
+		list_for_each_entry (t, &m->transfers, transfer_list) {
+			if (t->bits_per_word || t->speed_hz) {
+				status = mpc52xx_psc_spi_transfer_setup(spi, t);
+				if (status < 0)
+					break;
+			}
+
+			if (cs_change)
+				mpc52xx_psc_spi_activate_cs(spi);
+			cs_change = t->cs_change;
+
+			status = mpc52xx_psc_spi_transfer_rxtx(spi, t);
+			if (status)
+				break;
+			m->actual_length += t->len;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (cs_change)
+				mpc52xx_psc_spi_deactivate_cs(spi);
+		}
+
+		m->status = status;
+		m->complete(m->context);
+
+		if (status || !cs_change)
+			mpc52xx_psc_spi_deactivate_cs(spi);
+
+		mpc52xx_psc_spi_transfer_setup(spi, NULL);
+
+		spin_lock_irq(&mps->lock);
+	}
+	mps->busy = 0;
+	spin_unlock_irq(&mps->lock);
+}
+
+static int mpc52xx_psc_spi_setup(struct spi_device *spi)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	struct mpc52xx_psc_spi_cs *cs = spi->controller_state;
+	unsigned long flags;
+
+	if (spi->bits_per_word%8)
+		return -EINVAL;
+
+	if (!cs) {
+		cs = kzalloc(sizeof *cs, GFP_KERNEL);
+		if (!cs)
+			return -ENOMEM;
+		spi->controller_state = cs;
+	}
+
+	cs->bits_per_word = spi->bits_per_word;
+	cs->speed_hz = spi->max_speed_hz;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	if (!mps->busy)
+		mpc52xx_psc_spi_deactivate_cs(spi);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static int mpc52xx_psc_spi_transfer(struct spi_device *spi,
+		struct spi_message *m)
+{
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	spin_lock_irqsave(&mps->lock, flags);
+	list_add_tail(&m->queue, &mps->queue);
+	queue_work(mps->workqueue, &mps->work);
+	spin_unlock_irqrestore(&mps->lock, flags);
+
+	return 0;
+}
+
+static void mpc52xx_psc_spi_cleanup(struct spi_device *spi)
+{
+	kfree(spi->controller_state);
+}
+
+static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
+{
+	struct mpc52xx_cdm __iomem *cdm;
+	struct mpc52xx_gpio __iomem *gpio;
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+	u32 ul;
+	u32 mclken_div;
+	int ret = 0;
+
+#if defined(CONFIG_PPC_MERGE)
+	cdm = mpc52xx_find_and_map("mpc52xx-cdm");
+	gpio = mpc52xx_find_and_map("mpc52xx-gpio");
+#else
+	cdm = ioremap(MPC52xx_PA(MPC52xx_CDM_OFFSET), MPC52xx_CDM_SIZE);
+	gpio = ioremap(MPC52xx_PA(MPC52xx_GPIO_OFFSET), MPC52xx_GPIO_SIZE);
+#endif
+	if (!cdm || !gpio) {
+		printk(KERN_ERR "Error mapping CDM/GPIO\n");
+		ret = -EFAULT;
+		goto unmap_regs;
+	}
+
+	/* default sysclk is 512MHz */
+	mclken_div = 0x8000 |
+		(((mps->sysclk ? mps->sysclk : 512000000) / MCLK) & 0x1FF);
+
+	switch (psc_id) {
+	case 1:
+		ul = in_be32(&gpio->port_config);
+		ul &= 0xFFFFFFF8;
+		ul |= 0x00000006;
+		out_be32(&gpio->port_config, ul);
+		out_be16(&cdm->mclken_div_psc1, mclken_div);
+		ul = in_be32(&cdm->clk_enables);
+		ul |= 0x00000020;
+		out_be32(&cdm->clk_enables, ul);
+		break;
+	case 2:
+		ul = in_be32(&gpio->port_config);
+		ul &= 0xFFFFFF8F;
+		ul |= 0x00000060;
+		out_be32(&gpio->port_config, ul);
+		out_be16(&cdm->mclken_div_psc2, mclken_div);
+		ul = in_be32(&cdm->clk_enables);
+		ul |= 0x00000040;
+		out_be32(&cdm->clk_enables, ul);
+		break;
+	case 3:
+		ul = in_be32(&gpio->port_config);
+		ul &= 0xFFFFF0FF;
+		ul |= 0x00000600;
+		out_be32(&gpio->port_config, ul);
+		out_be16(&cdm->mclken_div_psc3, mclken_div);
+		ul = in_be32(&cdm->clk_enables);
+		ul |= 0x00000080;
+		out_be32(&cdm->clk_enables, ul);
+		break;
+	case 6:
+		ul = in_be32(&gpio->port_config);
+		ul &= 0xFF8FFFFF;
+		ul |= 0x00700000;
+		out_be32(&gpio->port_config, ul);
+		out_be16(&cdm->mclken_div_psc6, mclken_div);
+		ul = in_be32(&cdm->clk_enables);
+		ul |= 0x00000010;
+		out_be32(&cdm->clk_enables, ul);
+		break;
+	default:
+		ret = -EINVAL;
+		goto unmap_regs;
+	}
+
+	/* Reset the PSC into a known state */
+	out_8(&psc->command, MPC52xx_PSC_RST_RX);
+	out_8(&psc->command, MPC52xx_PSC_RST_TX);
+	out_8(&psc->command, MPC52xx_PSC_TX_DISABLE | MPC52xx_PSC_RX_DISABLE);
+
+	/* Disable interrupts, interrupts are based on alarm level */
+	out_be16(&psc->mpc52xx_psc_imr, 0);
+	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
+	out_8(&psc->rfcntl, 0);
+	out_8(&psc->mode, MPC52xx_PSC_MODE_FFULL);
+
+	/* Configure 8bit codec mode as a SPI master and use EOF flags */
+	/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
+	out_be32(&psc->sicr, 0x0180C800);
+	out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
+
+	/* Set 2ms DTL delay */
+	out_8(&psc->ctur, 0x00);
+	out_8(&psc->ctlr, 0x84);
+
+	mps->bits_per_word = 8;
+
+unmap_regs:
+	if (cdm)
+		iounmap(cdm);
+	if (gpio)
+		iounmap(gpio);
+
+	return ret;
+}
+
+static irqreturn_t mpc52xx_psc_spi_isr(int irq, void *dev_id)
+{
+	struct mpc52xx_psc_spi *mps = (struct mpc52xx_psc_spi *)dev_id;
+	struct mpc52xx_psc __iomem *psc = mps->psc;
+
+	/* disable interrupt and wake up the work queue */
+	if (in_be16(&psc->mpc52xx_psc_isr) & MPC52xx_PSC_IMR_RXRDY) {
+		out_be16(&psc->mpc52xx_psc_imr, 0);
+		complete(&mps->done);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/* bus_num is used only for the case dev->platform_data == NULL */
+static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr,
+				u32 size, unsigned int irq, s16 bus_num)
+{
+	struct fsl_spi_platform_data *pdata = dev->platform_data;
+	struct mpc52xx_psc_spi *mps;
+	struct spi_master *master;
+	int ret;
+
+	if (pdata == NULL)
+		return -ENODEV;
+
+	master = spi_alloc_master(dev, sizeof *mps);
+	if (master == NULL)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, master);
+	mps = spi_master_get_devdata(master);
+
+	mps->irq = irq;
+	if (pdata == NULL) {
+		dev_warn(dev, "probe called without platform data, no "
+				"(de)activate_cs function will be called\n");
+		mps->activate_cs = NULL;
+		mps->deactivate_cs = NULL;
+		mps->sysclk = 0;
+		master->bus_num = bus_num;
+		master->num_chipselect = 255;
+	} else {
+		mps->activate_cs = pdata->activate_cs;
+		mps->deactivate_cs = pdata->deactivate_cs;
+		mps->sysclk = pdata->sysclk;
+		master->bus_num = pdata->bus_num;
+		master->num_chipselect = pdata->max_chipselect;
+	}
+	master->setup = mpc52xx_psc_spi_setup;
+	master->transfer = mpc52xx_psc_spi_transfer;
+	master->cleanup = mpc52xx_psc_spi_cleanup;
+
+	mps->psc = ioremap(regaddr, size);
+	if (!mps->psc) {
+		dev_err(dev, "could not ioremap I/O port range\n");
+		ret = -EFAULT;
+		goto free_master;
+	}
+
+	ret = request_irq(mps->irq, mpc52xx_psc_spi_isr, 0, "mpc52xx-psc-spi",
+				mps);
+	if (ret)
+		goto free_master;
+
+	ret = mpc52xx_psc_spi_port_config(master->bus_num, mps);
+	if (ret < 0)
+		goto free_irq;
+
+	spin_lock_init(&mps->lock);
+	init_completion(&mps->done);
+	INIT_WORK(&mps->work, mpc52xx_psc_spi_work);
+	INIT_LIST_HEAD(&mps->queue);
+
+	mps->workqueue = create_singlethread_workqueue(
+		master->cdev.dev->bus_id);
+	if (mps->workqueue == NULL) {
+		ret = -EBUSY;
+		goto free_irq;
+	}
+
+	ret = spi_register_master(master);
+	if (ret < 0)
+		goto unreg_master;
+
+	return ret;
+
+unreg_master:
+	destroy_workqueue(mps->workqueue);
+free_irq:
+	free_irq(mps->irq, mps);
+free_master:
+	if (mps->psc)
+		iounmap(mps->psc);
+	spi_master_put(master);
+
+	return ret;
+}
+
+static int __exit mpc52xx_psc_spi_do_remove(struct device *dev)
+{
+	struct spi_master *master = dev_get_drvdata(dev);
+	struct mpc52xx_psc_spi *mps = spi_master_get_devdata(master);
+
+	flush_workqueue(mps->workqueue);
+	destroy_workqueue(mps->workqueue);
+	spi_unregister_master(master);
+	free_irq(mps->irq, mps);
+	if (mps->psc)
+		iounmap(mps->psc);
+
+	return 0;
+}
+
+#if !defined(CONFIG_PPC_MERGE)
+static int __init mpc52xx_psc_spi_probe(struct platform_device *dev)
+{
+	switch(dev->id) {
+	case 1:
+	case 2:
+	case 3:
+	case 6:
+		return mpc52xx_psc_spi_do_probe(&dev->dev,
+			MPC52xx_PA(MPC52xx_PSCx_OFFSET(dev->id)),
+			MPC52xx_PSC_SIZE, platform_get_irq(dev, 0), dev->id);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int __exit mpc52xx_psc_spi_remove(struct platform_device *dev)
+{
+	return mpc52xx_psc_spi_do_remove(&dev->dev);
+}
+
+static struct platform_driver mpc52xx_psc_spi_platform_driver = {
+	.remove = __exit_p(mpc52xx_psc_spi_remove),
+	.driver = {
+		.name = "mpc52xx-psc-spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mpc52xx_psc_spi_init(void)
+{
+	return platform_driver_probe(&mpc52xx_psc_spi_platform_driver,
+			mpc52xx_psc_spi_probe);
+}
+module_init(mpc52xx_psc_spi_init);
+
+static void __exit mpc52xx_psc_spi_exit(void)
+{
+	platform_driver_unregister(&mpc52xx_psc_spi_platform_driver);
+}
+module_exit(mpc52xx_psc_spi_exit);
+
+#else	/* defined(CONFIG_PPC_MERGE) */
+
+static int __init mpc52xx_psc_spi_of_probe(struct of_device *op,
+	const struct of_device_id *match)
+{
+	const u32 *regaddr_p;
+	u64 regaddr64, size64;
+	s16 id = -1;
+
+	regaddr_p = of_get_address(op->node, 0, &size64, NULL);
+	if (!regaddr_p) {
+		printk(KERN_ERR "Invalid PSC address\n");
+		return -EINVAL;
+	}
+	regaddr64 = of_translate_address(op->node, regaddr_p);
+
+	if (op->dev.platform_data == NULL) {
+		struct device_node *np;
+		int i = 0;
+
+		for_each_node_by_type(np, "spi") {
+			if (of_find_device_by_node(np) == op) {
+				id = i;
+				break;
+			}
+			i++;
+		}
+	}
+
+	return mpc52xx_psc_spi_do_probe(&op->dev, (u32)regaddr64, (u32)size64,
+					irq_of_parse_and_map(op->node, 0), id);
+}
+
+static int __exit mpc52xx_psc_spi_of_remove(struct of_device *op)
+{
+	return mpc52xx_psc_spi_do_remove(&op->dev);
+}
+
+static struct of_device_id mpc52xx_psc_spi_of_match[] = {
+	{ .type = "spi", .compatible = "mpc52xx-psc-spi", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
+
+static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
+	.owner = THIS_MODULE,
+	.name = "mpc52xx-psc-spi",
+	.match_table = mpc52xx_psc_spi_of_match,
+	.probe = mpc52xx_psc_spi_of_probe,
+	.remove = __exit_p(mpc52xx_psc_spi_of_remove),
+	.driver = {
+		.name = "mpc52xx-psc-spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init mpc52xx_psc_spi_init(void)
+{
+	return of_register_platform_driver(&mpc52xx_psc_spi_of_driver);
+}
+module_init(mpc52xx_psc_spi_init);
+
+static void __exit mpc52xx_psc_spi_exit(void)
+{
+	of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver);
+}
+module_exit(mpc52xx_psc_spi_exit);
+
+#endif	/* defined(CONFIG_PPC_MERGE) */
+
+MODULE_AUTHOR("Dragos Carp");
+MODULE_DESCRIPTION("MPC52xx PSC SPI Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/telephony/Kconfig b/drivers/telephony/Kconfig
index 7625b18..dd1d6a5 100644
--- a/drivers/telephony/Kconfig
+++ b/drivers/telephony/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Telephony Support"
+	depends on HAS_IOMEM
 
 config PHONE
 	tristate "Linux telephony support"
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 278a22c..15499b7 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "USB support"
+	depends on HAS_IOMEM
 
 # Host-side USB depends on having a host controller
 # NOTE:  dummy_hcd is always an option, but it's ignored here ...
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9a256d2..eebcb70 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -3,6 +3,7 @@
 #
 
 menu "Graphics support"
+	depends on HAS_IOMEM
 
 source "drivers/video/backlight/Kconfig"
 source "drivers/video/display/Kconfig"
@@ -747,6 +748,22 @@
 	  working with S1D13806). Product specs at
 	  <http://www.erd.epson.com/vdc/html/legacy_13xxx.htm>
 
+config FB_ATMEL
+	tristate "AT91/AT32 LCD Controller support"
+	depends on FB && (ARCH_AT91SAM9261 || ARCH_AT91SAM9263 || AVR32)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	help
+	  This enables support for the AT91/AT32 LCD Controller.
+
+config FB_INTSRAM
+	bool "Frame Buffer in internal SRAM"
+	depends on FB_ATMEL && ARCH_AT91SAM9261
+	help
+	  Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want
+	  to let frame buffer in external SDRAM.
+
 config FB_NVIDIA
 	tristate "nVidia Framebuffer Support"
 	depends on FB && PCI
@@ -779,6 +796,15 @@
 	  independently validate video mode parameters, you should say Y
 	  here.
 
+config FB_NVIDIA_DEBUG
+	bool "Lots of debug output"
+	depends on FB_NVIDIA
+	default n
+	help
+	  Say Y here if you want the nVidia driver to output all sorts
+	  of debugging information to provide to the maintainer when
+	  something goes wrong.
+
 config FB_NVIDIA_BACKLIGHT
 	bool "Support for backlight control"
 	depends on FB_NVIDIA
@@ -818,7 +844,7 @@
 	  here.
 
 config FB_RIVA_DEBUG
-	bool "Lots of debug output from Riva(nVidia) driver"
+	bool "Lots of debug output"
 	depends on FB_RIVA
 	default n
 	help
@@ -1430,8 +1456,11 @@
 	  and ICS 5342 RAMDAC.
 
 config FB_PM3
-	tristate "Permedia3 support"
-	depends on FB && PCI && BROKEN
+	tristate "Permedia3 support (EXPERIMENTAL)"
+	depends on FB && PCI && EXPERIMENTAL
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
 	help
 	  This is the frame buffer device driver for the 3DLabs Permedia3
 	  chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 &
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 0b70567..bd8b052 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -87,6 +87,7 @@
 obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_HIT)              += hitfb.o
 obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
+obj-$(CONFIG_FB_ATMEL)		  += atmel_lcdfb.o
 obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
 obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
 obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
new file mode 100644
index 0000000..e1d5bd0
--- /dev/null
+++ b/drivers/video/atmel_lcdfb.c
@@ -0,0 +1,752 @@
+/*
+ *  Driver for AT91/AT32 LCD Controller
+ *
+ *  Copyright (C) 2007 Atmel Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive for
+ * more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/arch/board.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+
+#include <video/atmel_lcdc.h>
+
+#define lcdc_readl(sinfo, reg)		__raw_readl((sinfo)->mmio+(reg))
+#define lcdc_writel(sinfo, reg, val)	__raw_writel((val), (sinfo)->mmio+(reg))
+
+/* configurable parameters */
+#define ATMEL_LCDC_CVAL_DEFAULT		0xc8
+#define ATMEL_LCDC_DMA_BURST_LEN	8
+
+#if defined(CONFIG_ARCH_AT91SAM9263)
+#define ATMEL_LCDC_FIFO_SIZE		2048
+#else
+#define ATMEL_LCDC_FIFO_SIZE		512
+#endif
+
+#if defined(CONFIG_ARCH_AT91)
+#define	ATMEL_LCDFB_FBINFO_DEFAULT	FBINFO_DEFAULT
+
+static inline void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+					struct fb_var_screeninfo *var)
+{
+
+}
+#elif defined(CONFIG_AVR32)
+#define	ATMEL_LCDFB_FBINFO_DEFAULT	(FBINFO_DEFAULT \
+					| FBINFO_PARTIAL_PAN_OK \
+					| FBINFO_HWACCEL_XPAN \
+					| FBINFO_HWACCEL_YPAN)
+
+static void atmel_lcdfb_update_dma2d(struct atmel_lcdfb_info *sinfo,
+				     struct fb_var_screeninfo *var)
+{
+	u32 dma2dcfg;
+	u32 pixeloff;
+
+	pixeloff = (var->xoffset * var->bits_per_pixel) & 0x1f;
+
+	dma2dcfg = ((var->xres_virtual - var->xres) * var->bits_per_pixel) / 8;
+	dma2dcfg |= pixeloff << ATMEL_LCDC_PIXELOFF_OFFSET;
+	lcdc_writel(sinfo, ATMEL_LCDC_DMA2DCFG, dma2dcfg);
+
+	/* Update configuration */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON,
+		    lcdc_readl(sinfo, ATMEL_LCDC_DMACON)
+		    | ATMEL_LCDC_DMAUPDT);
+}
+#endif
+
+
+static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.visual		= FB_VISUAL_TRUECOLOR,
+	.xpanstep	= 0,
+	.ypanstep	= 0,
+	.ywrapstep	= 0,
+	.accel		= FB_ACCEL_NONE,
+};
+
+
+static void atmel_lcdfb_update_dma(struct fb_info *info,
+			       struct fb_var_screeninfo *var)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	struct fb_fix_screeninfo *fix = &info->fix;
+	unsigned long dma_addr;
+
+	dma_addr = (fix->smem_start + var->yoffset * fix->line_length
+		    + var->xoffset * var->bits_per_pixel / 8);
+
+	dma_addr &= ~3UL;
+
+	/* Set framebuffer DMA base address and pixel offset */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMABADDR1, dma_addr);
+
+	atmel_lcdfb_update_dma2d(sinfo, var);
+}
+
+static inline void atmel_lcdfb_free_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+
+	dma_free_writecombine(info->device, info->fix.smem_len,
+				info->screen_base, info->fix.smem_start);
+}
+
+/**
+ *	atmel_lcdfb_alloc_video_memory - Allocate framebuffer memory
+ *	@sinfo: the frame buffer to allocate memory for
+ */
+static int atmel_lcdfb_alloc_video_memory(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	struct fb_var_screeninfo *var = &info->var;
+
+	info->fix.smem_len = (var->xres_virtual * var->yres_virtual
+			    * ((var->bits_per_pixel + 7) / 8));
+
+	info->screen_base = dma_alloc_writecombine(info->device, info->fix.smem_len,
+					(dma_addr_t *)&info->fix.smem_start, GFP_KERNEL);
+
+	if (!info->screen_base) {
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/**
+ *      atmel_lcdfb_check_var - Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Checks to see if the hardware supports the state requested by
+ *	var passed in. This function does not alter the hardware
+ *	state!!!  This means the data stored in struct fb_info and
+ *	struct atmel_lcdfb_info do not change. This includes the var
+ *	inside of struct fb_info.  Do NOT change these. This function
+ *	can be called on its own if we intent to only test a mode and
+ *	not actually set it. The stuff in modedb.c is a example of
+ *	this. If the var passed in is slightly off by what the
+ *	hardware can support then we alter the var PASSED in to what
+ *	we can do. If the hardware doesn't support mode change a
+ *	-EINVAL will be returned by the upper layers. You don't need
+ *	to implement this function then. If you hardware doesn't
+ *	support changing the resolution then this function is not
+ *	needed. In this case the driver would just provide a var that
+ *	represents the static state the screen is in.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+	struct device *dev = info->device;
+	struct atmel_lcdfb_info *sinfo = info->par;
+	unsigned long clk_value_khz;
+
+	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+	dev_dbg(dev, "%s:\n", __func__);
+	dev_dbg(dev, "  resolution: %ux%u\n", var->xres, var->yres);
+	dev_dbg(dev, "  pixclk:     %lu KHz\n", PICOS2KHZ(var->pixclock));
+	dev_dbg(dev, "  bpp:        %u\n", var->bits_per_pixel);
+	dev_dbg(dev, "  clk:        %lu KHz\n", clk_value_khz);
+
+	if ((PICOS2KHZ(var->pixclock) * var->bits_per_pixel / 8) > clk_value_khz) {
+		dev_err(dev, "%lu KHz pixel clock is too fast\n", PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	/* Force same alignment for each line */
+	var->xres = (var->xres + 3) & ~3UL;
+	var->xres_virtual = (var->xres_virtual + 3) & ~3UL;
+
+	var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+	var->transp.offset = var->transp.length = 0;
+	var->xoffset = var->yoffset = 0;
+
+	switch (var->bits_per_pixel) {
+	case 2:
+	case 4:
+	case 8:
+		var->red.offset = var->green.offset = var->blue.offset = 0;
+		var->red.length = var->green.length = var->blue.length
+			= var->bits_per_pixel;
+		break;
+	case 15:
+	case 16:
+		var->red.offset = 0;
+		var->green.offset = 5;
+		var->blue.offset = 10;
+		var->red.length = var->green.length = var->blue.length = 5;
+		break;
+	case 24:
+	case 32:
+		var->red.offset = 0;
+		var->green.offset = 8;
+		var->blue.offset = 16;
+		var->red.length = var->green.length = var->blue.length = 8;
+		break;
+	default:
+		dev_err(dev, "color depth %d not supported\n",
+					var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ *      atmel_lcdfb_set_par - Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the resolution
+ *	of the this particular framebuffer. This function alters the
+ *	par AND the fb_fix_screeninfo stored in fb_info. It doesn't
+ *	not alter var in fb_info since we are using that data. This
+ *	means we depend on the data in var inside fb_info to be
+ *	supported by the hardware.  atmel_lcdfb_check_var is always called
+ *	before atmel_lcdfb_set_par to ensure this.  Again if you can't
+ *	change the resolution you don't need this function.
+ *
+ */
+static int atmel_lcdfb_set_par(struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	unsigned long value;
+	unsigned long clk_value_khz;
+
+	dev_dbg(info->device, "%s:\n", __func__);
+	dev_dbg(info->device, "  * resolution: %ux%u (%ux%u virtual)\n",
+		 info->var.xres, info->var.yres,
+		 info->var.xres_virtual, info->var.yres_virtual);
+
+	/* Turn off the LCD controller and the DMA controller */
+	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON, sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET);
+
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, 0);
+
+	if (info->var.bits_per_pixel <= 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	info->fix.line_length = info->var.xres_virtual * (info->var.bits_per_pixel / 8);
+
+	/* Re-initialize the DMA engine... */
+	dev_dbg(info->device, "  * update DMA engine\n");
+	atmel_lcdfb_update_dma(info, &info->var);
+
+	/* ...set frame size and burst length = 8 words (?) */
+	value = (info->var.yres * info->var.xres * info->var.bits_per_pixel) / 32;
+	value |= ((ATMEL_LCDC_DMA_BURST_LEN - 1) << ATMEL_LCDC_BLENGTH_OFFSET);
+	lcdc_writel(sinfo, ATMEL_LCDC_DMAFRMCFG, value);
+
+	/* Now, the LCDC core... */
+
+	/* Set pixel clock */
+	clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
+
+	value = clk_value_khz / PICOS2KHZ(info->var.pixclock);
+
+	if (clk_value_khz % PICOS2KHZ(info->var.pixclock))
+		value++;
+
+	value = (value / 2) - 1;
+
+	if (value <= 0) {
+		dev_notice(info->device, "Bypassing pixel clock divider\n");
+		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS);
+	} else
+		lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET);
+
+	/* Initialize control register 2 */
+	value = sinfo->default_lcdcon2;
+
+	if (!(info->var.sync & FB_SYNC_HOR_HIGH_ACT))
+		value |= ATMEL_LCDC_INVLINE_INVERTED;
+	if (!(info->var.sync & FB_SYNC_VERT_HIGH_ACT))
+		value |= ATMEL_LCDC_INVFRAME_INVERTED;
+
+	switch (info->var.bits_per_pixel) {
+		case 1:	value |= ATMEL_LCDC_PIXELSIZE_1; break;
+		case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break;
+		case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break;
+		case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break;
+		case 15: /* fall through */
+		case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break;
+		case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break;
+		case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break;
+		default: BUG(); break;
+	}
+	dev_dbg(info->device, "  * LCDCON2 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_LCDCON2, value);
+
+	/* Vertical timing */
+	value = (info->var.vsync_len - 1) << ATMEL_LCDC_VPW_OFFSET;
+	value |= info->var.upper_margin << ATMEL_LCDC_VBP_OFFSET;
+	value |= info->var.lower_margin;
+	dev_dbg(info->device, "  * LCDTIM1 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_TIM1, value);
+
+	/* Horizontal timing */
+	value = (info->var.right_margin - 1) << ATMEL_LCDC_HFP_OFFSET;
+	value |= (info->var.hsync_len - 1) << ATMEL_LCDC_HPW_OFFSET;
+	value |= (info->var.left_margin - 1);
+	dev_dbg(info->device, "  * LCDTIM2 = %08lx\n", value);
+	lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
+
+	/* Display size */
+	value = (info->var.xres - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
+	value |= info->var.yres - 1;
+	lcdc_writel(sinfo, ATMEL_LCDC_LCDFRMCFG, value);
+
+	/* FIFO Threshold: Use formula from data sheet */
+	value = ATMEL_LCDC_FIFO_SIZE - (2 * ATMEL_LCDC_DMA_BURST_LEN + 3);
+	lcdc_writel(sinfo, ATMEL_LCDC_FIFO, value);
+
+	/* Toggle LCD_MODE every frame */
+	lcdc_writel(sinfo, ATMEL_LCDC_MVAL, 0);
+
+	/* Disable all interrupts */
+	lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
+
+	/* Set contrast */
+	value = ATMEL_LCDC_PS_DIV8 | ATMEL_LCDC_POL_POSITIVE | ATMEL_LCDC_ENA_PWMENABLE;
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, value);
+	lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_VAL, ATMEL_LCDC_CVAL_DEFAULT);
+	/* ...wait for DMA engine to become idle... */
+	while (lcdc_readl(sinfo, ATMEL_LCDC_DMACON) & ATMEL_LCDC_DMABUSY)
+		msleep(10);
+
+	dev_dbg(info->device, "  * re-enable DMA engine\n");
+	/* ...and enable it with updated configuration */
+	lcdc_writel(sinfo, ATMEL_LCDC_DMACON, sinfo->default_dmacon);
+
+	dev_dbg(info->device, "  * re-enable LCDC core\n");
+	lcdc_writel(sinfo, ATMEL_LCDC_PWRCON,
+		(sinfo->guard_time << ATMEL_LCDC_GUARDT_OFFSET) | ATMEL_LCDC_PWR);
+
+	dev_dbg(info->device, "  * DONE\n");
+
+	return 0;
+}
+
+static inline unsigned int chan_to_field(unsigned int chan, const struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+/**
+ *  	atmel_lcdfb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware.
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a psuedo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function.
+ *
+ *	Returns negative errno on error, or zero on success. In an
+ *	ideal world, this would have been the case, but as it turns
+ *	out, the other drivers return 1 on failure, so that's what
+ *	we're going to do.
+ */
+static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
+			     unsigned int green, unsigned int blue,
+			     unsigned int transp, struct fb_info *info)
+{
+	struct atmel_lcdfb_info *sinfo = info->par;
+	unsigned int val;
+	u32 *pal;
+	int ret = 1;
+
+	if (info->var.grayscale)
+		red = green = blue = (19595 * red + 38470 * green
+				      + 7471 * blue) >> 16;
+
+	switch (info->fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &info->var.red);
+			val |= chan_to_field(green, &info->var.green);
+			val |= chan_to_field(blue, &info->var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_PSEUDOCOLOR:
+		if (regno < 256) {
+			val  = ((red   >> 11) & 0x001f);
+			val |= ((green >>  6) & 0x03e0);
+			val |= ((blue  >>  1) & 0x7c00);
+
+			/*
+			 * TODO: intensity bit. Maybe something like
+			 *   ~(red[10] ^ green[10] ^ blue[10]) & 1
+			 */
+
+			lcdc_writel(sinfo, ATMEL_LCDC_LUT(regno), val);
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int atmel_lcdfb_pan_display(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	dev_dbg(info->device, "%s\n", __func__);
+
+	atmel_lcdfb_update_dma(info, var);
+
+	return 0;
+}
+
+static struct fb_ops atmel_lcdfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= atmel_lcdfb_check_var,
+	.fb_set_par	= atmel_lcdfb_set_par,
+	.fb_setcolreg	= atmel_lcdfb_setcolreg,
+	.fb_pan_display	= atmel_lcdfb_pan_display,
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+};
+
+static irqreturn_t atmel_lcdfb_interrupt(int irq, void *dev_id)
+{
+	struct fb_info *info = dev_id;
+	struct atmel_lcdfb_info *sinfo = info->par;
+	u32 status;
+
+	status = lcdc_readl(sinfo, ATMEL_LCDC_ISR);
+	lcdc_writel(sinfo, ATMEL_LCDC_IDR, status);
+	return IRQ_HANDLED;
+}
+
+static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
+{
+	struct fb_info *info = sinfo->info;
+	int ret = 0;
+
+	memset_io(info->screen_base, 0, info->fix.smem_len);
+	info->var.activate |= FB_ACTIVATE_FORCE | FB_ACTIVATE_NOW;
+
+	dev_info(info->device,
+	       "%luKiB frame buffer at %08lx (mapped at %p)\n",
+	       (unsigned long)info->fix.smem_len / 1024,
+	       (unsigned long)info->fix.smem_start,
+	       info->screen_base);
+
+	/* Allocate colormap */
+	ret = fb_alloc_cmap(&info->cmap, 256, 0);
+	if (ret < 0)
+		dev_err(info->device, "Alloc color map failed\n");
+
+	return ret;
+}
+
+static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
+{
+	if (sinfo->bus_clk)
+		clk_enable(sinfo->bus_clk);
+	clk_enable(sinfo->lcdc_clk);
+}
+
+static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
+{
+	if (sinfo->bus_clk)
+		clk_disable(sinfo->bus_clk);
+	clk_disable(sinfo->lcdc_clk);
+}
+
+
+static int __init atmel_lcdfb_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fb_info *info;
+	struct atmel_lcdfb_info *sinfo;
+	struct atmel_lcdfb_info *pdata_sinfo;
+	struct resource *regs = NULL;
+	struct resource *map = NULL;
+	int ret;
+
+	dev_dbg(dev, "%s BEGIN\n", __func__);
+
+	ret = -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct atmel_lcdfb_info), dev);
+	if (!info) {
+		dev_err(dev, "cannot allocate memory\n");
+		goto out;
+	}
+
+	sinfo = info->par;
+
+	if (dev->platform_data) {
+		pdata_sinfo = (struct atmel_lcdfb_info *)dev->platform_data;
+		sinfo->default_bpp = pdata_sinfo->default_bpp;
+		sinfo->default_dmacon = pdata_sinfo->default_dmacon;
+		sinfo->default_lcdcon2 = pdata_sinfo->default_lcdcon2;
+		sinfo->default_monspecs = pdata_sinfo->default_monspecs;
+		sinfo->atmel_lcdfb_power_control = pdata_sinfo->atmel_lcdfb_power_control;
+		sinfo->guard_time = pdata_sinfo->guard_time;
+	} else {
+		dev_err(dev, "cannot get default configuration\n");
+		goto free_info;
+	}
+	sinfo->info = info;
+	sinfo->pdev = pdev;
+
+	strcpy(info->fix.id, sinfo->pdev->name);
+	info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
+	info->pseudo_palette = sinfo->pseudo_palette;
+	info->fbops = &atmel_lcdfb_ops;
+
+	memcpy(&info->monspecs, sinfo->default_monspecs, sizeof(info->monspecs));
+	info->fix = atmel_lcdfb_fix;
+
+	/* Enable LCDC Clocks */
+	if (cpu_is_at91sam9261() || cpu_is_at32ap7000()) {
+		sinfo->bus_clk = clk_get(dev, "hck1");
+		if (IS_ERR(sinfo->bus_clk)) {
+			ret = PTR_ERR(sinfo->bus_clk);
+			goto free_info;
+		}
+	}
+	sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
+	if (IS_ERR(sinfo->lcdc_clk)) {
+		ret = PTR_ERR(sinfo->lcdc_clk);
+		goto put_bus_clk;
+	}
+	atmel_lcdfb_start_clock(sinfo);
+
+	ret = fb_find_mode(&info->var, info, NULL, info->monspecs.modedb,
+			info->monspecs.modedb_len, info->monspecs.modedb,
+			sinfo->default_bpp);
+	if (!ret) {
+		dev_err(dev, "no suitable video mode found\n");
+		goto stop_clk;
+	}
+
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_err(dev, "resources unusable\n");
+		ret = -ENXIO;
+		goto stop_clk;
+	}
+
+	sinfo->irq_base = platform_get_irq(pdev, 0);
+	if (sinfo->irq_base < 0) {
+		dev_err(dev, "unable to get irq\n");
+		ret = sinfo->irq_base;
+		goto stop_clk;
+	}
+
+	/* Initialize video memory */
+	map = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (map) {
+		/* use a pre-allocated memory buffer */
+		info->fix.smem_start = map->start;
+		info->fix.smem_len = map->end - map->start + 1;
+		if (!request_mem_region(info->fix.smem_start,
+					info->fix.smem_len, pdev->name)) {
+			ret = -EBUSY;
+			goto stop_clk;
+		}
+
+		info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+		if (!info->screen_base)
+			goto release_intmem;
+	} else {
+		/* alocate memory buffer */
+		ret = atmel_lcdfb_alloc_video_memory(sinfo);
+		if (ret < 0) {
+			dev_err(dev, "cannot allocate framebuffer: %d\n", ret);
+			goto stop_clk;
+		}
+	}
+
+	/* LCDC registers */
+	info->fix.mmio_start = regs->start;
+	info->fix.mmio_len = regs->end - regs->start + 1;
+
+	if (!request_mem_region(info->fix.mmio_start,
+				info->fix.mmio_len, pdev->name)) {
+		ret = -EBUSY;
+		goto free_fb;
+	}
+
+	sinfo->mmio = ioremap(info->fix.mmio_start, info->fix.mmio_len);
+	if (!sinfo->mmio) {
+		dev_err(dev, "cannot map LCDC registers\n");
+		goto release_mem;
+	}
+
+	/* interrupt */
+	ret = request_irq(sinfo->irq_base, atmel_lcdfb_interrupt, 0, pdev->name, info);
+	if (ret) {
+		dev_err(dev, "request_irq failed: %d\n", ret);
+		goto unmap_mmio;
+	}
+
+	ret = atmel_lcdfb_init_fbinfo(sinfo);
+	if (ret < 0) {
+		dev_err(dev, "init fbinfo failed: %d\n", ret);
+		goto unregister_irqs;
+	}
+
+	/*
+	 * This makes sure that our colour bitfield
+	 * descriptors are correctly initialised.
+	 */
+	atmel_lcdfb_check_var(&info->var, info);
+
+	ret = fb_set_var(info, &info->var);
+	if (ret) {
+		dev_warn(dev, "unable to set display parameters\n");
+		goto free_cmap;
+	}
+
+	dev_set_drvdata(dev, info);
+
+	/*
+	 * Tell the world that we're ready to go
+	 */
+	ret = register_framebuffer(info);
+	if (ret < 0) {
+		dev_err(dev, "failed to register framebuffer device: %d\n", ret);
+		goto free_cmap;
+	}
+
+	/* Power up the LCDC screen */
+	if (sinfo->atmel_lcdfb_power_control)
+		sinfo->atmel_lcdfb_power_control(1);
+
+	dev_info(dev, "fb%d: Atmel LCDC at 0x%08lx (mapped at %p), irq %lu\n",
+		       info->node, info->fix.mmio_start, sinfo->mmio, sinfo->irq_base);
+
+	return 0;
+
+
+free_cmap:
+	fb_dealloc_cmap(&info->cmap);
+unregister_irqs:
+	free_irq(sinfo->irq_base, info);
+unmap_mmio:
+	iounmap(sinfo->mmio);
+release_mem:
+ 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+free_fb:
+	if (map)
+		iounmap(info->screen_base);
+	else
+		atmel_lcdfb_free_video_memory(sinfo);
+
+release_intmem:
+	if (map)
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+stop_clk:
+	atmel_lcdfb_stop_clock(sinfo);
+	clk_put(sinfo->lcdc_clk);
+put_bus_clk:
+	if (sinfo->bus_clk)
+		clk_put(sinfo->bus_clk);
+free_info:
+	framebuffer_release(info);
+out:
+	dev_dbg(dev, "%s FAILED\n", __func__);
+	return ret;
+}
+
+static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct atmel_lcdfb_info *sinfo = info->par;
+
+	if (!sinfo)
+		return 0;
+
+	if (sinfo->atmel_lcdfb_power_control)
+		sinfo->atmel_lcdfb_power_control(0);
+	unregister_framebuffer(info);
+	atmel_lcdfb_stop_clock(sinfo);
+	clk_put(sinfo->lcdc_clk);
+	if (sinfo->bus_clk)
+		clk_put(sinfo->bus_clk);
+	fb_dealloc_cmap(&info->cmap);
+	free_irq(sinfo->irq_base, info);
+	iounmap(sinfo->mmio);
+ 	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+	if (platform_get_resource(pdev, IORESOURCE_MEM, 1)) {
+		iounmap(info->screen_base);
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+	} else {
+		atmel_lcdfb_free_video_memory(sinfo);
+	}
+
+	dev_set_drvdata(dev, NULL);
+	framebuffer_release(info);
+
+	return 0;
+}
+
+static struct platform_driver atmel_lcdfb_driver = {
+	.remove		= __exit_p(atmel_lcdfb_remove),
+	.driver		= {
+		.name	= "atmel_lcdfb",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init atmel_lcdfb_init(void)
+{
+	return platform_driver_probe(&atmel_lcdfb_driver, atmel_lcdfb_probe);
+}
+
+static void __exit atmel_lcdfb_exit(void)
+{
+	platform_driver_unregister(&atmel_lcdfb_driver);
+}
+
+module_init(atmel_lcdfb_init);
+module_exit(atmel_lcdfb_exit);
+
+MODULE_DESCRIPTION("AT91/AT32 LCD Controller framebuffer driver");
+MODULE_AUTHOR("Nicolas Ferre <nicolas.ferre@rfo.atmel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index aa3935d..63b85bf 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -19,13 +19,6 @@
 
 	  Say Y.
 
-#	if [ "$CONFIG_PCI" = "y" -a "$CONFIG_VGA_CONSOLE" = "y" ]; then
-#	   bool '   Allow VGA on any bus?' CONFIG_VGA_HOSE
-#	   if [ "$CONFIG_VGA_HOSE" = "y" ]; then
-#	      define_bool CONFIG_DUMMY_CONSOLE y
-#	   fi
-#	fi
-
 config VGACON_SOFT_SCROLLBACK
        bool "Enable Scrollback Buffer in System RAM"
        depends on VGA_CONSOLE
diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
index c627955..aff11bb 100644
--- a/drivers/video/nvidia/nv_hw.c
+++ b/drivers/video/nvidia/nv_hw.c
@@ -149,7 +149,9 @@
 		pll = NV_RD32(par->PMC, 0x4024);
 		M = pll & 0xFF;
 		N = (pll >> 8) & 0xFF;
-		if (((par->Chipset & 0xfff0) == 0x0290) || ((par->Chipset & 0xfff0) == 0x0390) || ((par->Chipset & 0xfff0) == 0x02E0)) {
+		if (((par->Chipset & 0xfff0) == 0x0290) ||
+			((par->Chipset & 0xfff0) == 0x0390) ||
+			((par->Chipset & 0xfff0) == 0x02E0)) {
 			MB = 1;
 			NB = 1;
 		} else {
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index f85edf0..41f6365 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -37,7 +37,6 @@
 #include "nv_proto.h"
 #include "nv_dma.h"
 
-#undef CONFIG_FB_NVIDIA_DEBUG
 #ifdef CONFIG_FB_NVIDIA_DEBUG
 #define NVTRACE          printk
 #else
diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
index 1ac5264..ab5e668 100644
--- a/drivers/video/pm2fb.c
+++ b/drivers/video/pm2fb.c
@@ -204,17 +204,6 @@
 }
 #endif
 
-static void wait_pm2(struct pm2fb_par* par) {
-
-	WAIT_FIFO(par, 1);
-	pm2_WR(par, PM2R_SYNC, 0);
-	mb();
-	do {
-		while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0);
-		rmb();
-	} while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
-}
-
 /*
  * partial products for the supported horizontal resolutions.
  */
@@ -1050,13 +1039,30 @@
 	return 0;
 }
 
+static int pm2fb_sync(struct fb_info *info)
+{
+	struct pm2fb_par *par = info->par;
+
+	WAIT_FIFO(par, 1);
+	pm2_WR(par, PM2R_SYNC, 0);
+	mb();
+	do {
+		while (pm2_RD(par, PM2R_OUT_FIFO_WORDS) == 0)
+			udelay(10);
+		rmb();
+	} while (pm2_RD(par, PM2R_OUT_FIFO) != PM2TAG(PM2R_SYNC));
+
+	return 0;
+}
+
 /*
  * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
  */
-static void pm2fb_block_op(struct pm2fb_par* par, int copy,
+static void pm2fb_block_op(struct fb_info* info, int copy,
 				s32 xsrc, s32 ysrc,
 				s32 x, s32 y, s32 w, s32 h,
 				u32 color) {
+	struct pm2fb_par *par = info->par;
 
 	if (!w || !h)
 		return;
@@ -1076,13 +1082,11 @@
 				(x<xsrc ? PM2F_INCREASE_X : 0) |
 				(y<ysrc ? PM2F_INCREASE_Y : 0) |
 				(copy ? 0 : PM2F_RENDER_FASTFILL));
-	wait_pm2(par);
 }
 
 static void pm2fb_fillrect (struct fb_info *info,
 				const struct fb_fillrect *region)
 {
-	struct pm2fb_par *par = info->par;
 	struct fb_fillrect modded;
 	int vxres, vyres;
 	u32 color = (info->fix.visual == FB_VISUAL_TRUECOLOR) ?
@@ -1116,7 +1120,7 @@
 		color |= color << 16;
 
 	if(info->var.bits_per_pixel != 24)
-		pm2fb_block_op(par, 0, 0, 0,
+		pm2fb_block_op(info, 0, 0, 0,
 				modded.dx, modded.dy,
 				modded.width, modded.height, color);
 	else
@@ -1126,7 +1130,6 @@
 static void pm2fb_copyarea(struct fb_info *info,
 				const struct fb_copyarea *area)
 {
-	struct pm2fb_par *par = info->par;
 	struct fb_copyarea modded;
 	u32 vxres, vyres;
 
@@ -1156,7 +1159,7 @@
 	if(modded.dy + modded.height > vyres)
 		modded.height = vyres - modded.dy;
 
-	pm2fb_block_op(par, 1, modded.sx, modded.sy,
+	pm2fb_block_op(info, 1, modded.sx, modded.sy,
 			modded.dx, modded.dy,
 			modded.width, modded.height, 0);
 }
@@ -1177,6 +1180,7 @@
 	.fb_fillrect	= pm2fb_fillrect,
 	.fb_copyarea	= pm2fb_copyarea,
 	.fb_imageblit	= cfb_imageblit,
+	.fb_sync	= pm2fb_sync,
 };
 
 /*
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index bd787e8..6c4dfcb0 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -1,55 +1,25 @@
 /*
  *  linux/drivers/video/pm3fb.c -- 3DLabs Permedia3 frame buffer device
- *  
- *  Copyright (C) 2001 Romain Dolbeau <dolbeau@irisa.fr>
+ *
+ *  Copyright (C) 2001 Romain Dolbeau <romain@dolbeau.org>.
+ *
+ *  Ported to 2.6 kernel on 1 May 2007 by Krzysztof Helt <krzysztof.h1@wp.pl>
+ *	based on pm2fb.c
+ *
  *  Based on code written by:
- *           Sven Luther, <luther@dpt-info.u-strasbg.fr>
- *           Alan Hourihane, <alanh@fairlite.demon.co.uk>
- *           Russell King, <rmk@arm.linux.org.uk>
+ *	   Sven Luther, <luther@dpt-info.u-strasbg.fr>
+ *	   Alan Hourihane, <alanh@fairlite.demon.co.uk>
+ *	   Russell King, <rmk@arm.linux.org.uk>
  *  Based on linux/drivers/video/skeletonfb.c:
  *	Copyright (C) 1997 Geert Uytterhoeven
  *  Based on linux/driver/video/pm2fb.c:
- *      Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- *      Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
+ *	Copyright (C) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ *	Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
  *
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive for
  *  more details.
  *
- *  $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $
- *
- *  CHANGELOG:
- *  Mon Feb 11 10:35:48 MET 2002, v 1.4.11B: Cosmetic update.
- *  Wed Jan 23 14:16:59 MET 2002, v 1.4.11: Preliminary 2.5.x support, patch for 2.5.2.
- *  Wed Nov 28 11:08:29 MET 2001, v 1.4.10: potential bug fix for SDRAM-based board, patch for 2.4.16.
- *  Thu Sep 20 10:24:42 MET DST 2001, v 1.4.9: sync bug fix, preliminary flatpanel support, better timings.
- *  Tue Aug 28 10:13:01 MET DST 2001, v 1.4.8: memory timings check, minor bug fixes.
- *  Wed Jul 18 19:06:14 CEST 2001, v 1.4.7: Mode fix (800x600-100, 1024x768-100 changed), using HW panning + accel bug fix.
- *  Mon Jun 25 10:33:56 MET DST 2001, v 1.4.6: Depth 12 fix, chip reset ioctl, moved memory erase ioctl to DEBUG.
- *  Wed Jun 20 11:13:08 MET DST 2001, v 1.4.5: Fixed missing blinking cursor in 8bpp, code cleaning, memory erase IOCTL.
- *  Mon Jun 18 16:00:27 CEST 2001, v 1.4.4: Depth 12 (RGBA 4444) support, code cleaning.
- *  Fri Jun 15 13:53:01 CEST 2001, v 1.4.3: Removed warnings, depth 15 support, add 'depth' option.
- *  Thu Jun 14 10:13:52 MET DST 2001, v 1.4.2: Fixed depth switching bug, preliminary 15bpp (RGB5551) support.
- *  Thu Apr 12 11:16:45 MET DST 2001, v 1.4.1B: Doc updates.
- *  Fri Apr  6 11:12:53 MET DST 2001, v 1.4.1: Configure.help, minor cleanup
- *  Thu Mar 29 10:56:50 MET DST 2001, v 1.4.0: Module & module options support (note: linux patch changed, 2.2.19 added).
- *  Thu Mar 15 15:30:31 MET 2001, v 1.3.2: Fixed mirroring bug on little-endian.
- *  Wed Mar 14 21:25:54 CET 2001, v 1.3.1: Fixed bug in BlockMove (_bmov).
- *  Tue Mar 13 10:53:19 MET 2001, v 1.3.0: Character drawing hardware support (in all width between 1 and 16), fixes.
- *  Thu Mar  8 10:20:16 MET 2001, v 1.2.2: Better J2000 support, "font:" option.
- *  Tue Mar  6 21:25:04 CET 2001, v 1.2.1: Better acceleration support.
- *  Mon Mar  5 21:54:17 CET 2001, v 1.2.0: Partial acceleration support (clear & bmove)
- *  Mon Mar  5 12:52:15 CET 2001, v 1.1.3: Big pan_display fix.
- *  Sun Mar  4 22:21:50 CET 2001, v 1.1.2: (numerous) bug fixes.
- *  Fri Mar  2 15:54:07 CET 2001, v 1.1.1: Might have Appian J2000 support, resource mangement in 2.4
- *  Wed Feb 28 18:21:35 CET 2001, v 1.1.0: Might have multiple boards support (added, but not yest tested)
- *  Tue Feb 27 17:31:12 CET 2001, v 1.0.6: fixes boot-time mode select, add more default mode
- *  Tue Feb 27 14:01:36 CET 2001, v 1.0.5: fixes (1.0.4 was broken for 2.2), cleaning up
- *  Mon Feb 26 23:17:36 CET 2001, v 1.0.4: preliminary 2.4.x support, dropped (useless on pm3) partial product, more OF fix
- *  Mon Feb 26 20:59:05 CET 2001, v 1.0.3: No more shadow register (and wasted memory), endianess fix, use OF-preset resolution by default
- *  Wed Feb 21 22:09:30 CET 2001, v 1.0.2: Code cleaning for future multiboard support, better OF support, bugs fix
- *  Wed Feb 21 19:58:56 CET 2001, v 1.0.1: OpenFirmware support, fixed memory detection, better debug support, code cleaning
- *  Wed Feb 21 14:47:06 CET 2001, v 1.0.0: First working version
  */
 
 #include <linux/module.h>
@@ -58,856 +28,155 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/delay.h>
-#include <linux/interrupt.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/ctype.h>
 
-#include <video/fbcon.h>
-#include <video/fbcon-mfb.h>
-#include <video/fbcon-cfb2.h>
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb24.h>
-#include <video/fbcon-cfb32.h>
 #include <video/pm3fb.h>
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#ifdef CONFIG_FB_OF
-#include <asm/prom.h>
+#if !defined(CONFIG_PCI)
+#error "Only generic PCI cards supported."
 #endif
 
-/* ************************************* */
-/* ***** The various "global" data ***** */
-/* ************************************* */
+#undef PM3FB_MASTER_DEBUG
+#ifdef PM3FB_MASTER_DEBUG
+#define DPRINTK(a,b...)	printk(KERN_DEBUG "pm3fb: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif
 
-/* those will need a rework for multiple board support */
-/* Driver name */
-static const char permedia3_name[16] = "Permedia3";
+/*
+ * Driver data
+ */
+static char *mode_option __devinitdata;
 
-/* the fb_par struct, mandatory */
-struct pm3fb_par {
-	u32 pixclock;		/* pixclock in KHz */
+/*
+ *  If your driver supports multiple boards, you should make the
+ *  below data types arrays, or allocate them dynamically (using kmalloc()).
+ */
 
-	u32 width;		/* width of virtual screen */
-	u32 height;		/* height of virtual screen */
-
-	u32 hsstart;		/* horiz. sync start */
-	u32 hsend;		/* horiz. sync end */
-	u32 hbend;		/* horiz. blank end (also gate end) */
-	u32 htotal;		/* total width (w/ sync & blank) */
-
-	u32 vsstart;		/* vert. sync start */
-	u32 vsend;		/* vert. sync end */
-	u32 vbend;		/* vert. blank end */
-	u32 vtotal;		/* total height (w/ sync & blank) */
-
-	u32 stride;		/* screen stride */
-	u32 base;		/* screen base (xoffset+yoffset) in 128 bits unit */
-	/* NOTE : unlike other pm3 stuff above, stored *after* shiftbpp. don't ask */
-	u32 depth;		/* screen depth (8, 12, 15, 16 or 32) */
-	u32 video;		/* video control (hsync,vsync) */
+/*
+ * This structure defines the hardware state of the graphics card. Normally
+ * you place this in a header file in linux/include/video. This file usually
+ * also includes register information. That allows other driver subsystems
+ * and userland applications the ability to use the same header file to
+ * avoid duplicate work and easy porting of software.
+ */
+struct pm3_par {
+	unsigned char	__iomem *v_regs;/* virtual address of p_regs */
+	u32		video;		/* video flags before blanking */
+	u32		base;		/* screen base (xoffset+yoffset) in 128 bits unit */
+	u32 		palette[16];
 };
 
-/* memory timings */
-struct pm3fb_timings
+/*
+ * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
+ * if we don't use modedb. If we do use modedb see pm3fb_init how to use it
+ * to get a fb_var_screeninfo. Otherwise define a default var as well.
+ */
+static struct fb_fix_screeninfo pm3fb_fix __devinitdata = {
+	.id =		"Permedia3",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_PSEUDOCOLOR,
+	.xpanstep =	1,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_NONE,
+};
+
+/*
+ * Utility functions
+ */
+
+static inline u32 PM3_READ_REG(struct pm3_par *par, s32 off)
 {
-	unsigned long caps;
-	unsigned long timings;
-	unsigned long control;
-	unsigned long refresh;
-	unsigned long powerdown;
-};
-typedef enum pm3fb_timing_result { pm3fb_timing_ok, pm3fb_timing_problem, pm3fb_timing_retry } pm3fb_timing_result;
-#define PM3FB_UNKNOWN_TIMING_VALUE ((unsigned long)-1)
-#define PM3FB_UNKNOWN_TIMINGS { PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE, PM3FB_UNKNOWN_TIMING_VALUE }
-
-/* the fb_info struct, mandatory */
-struct pm3fb_info {
-	struct fb_info_gen gen;
-	unsigned long board_num; /* internal board number */
-	unsigned long use_current;
-	struct pm3fb_par *current_par;
-	struct pci_dev *dev;    /* PCI device */
-	unsigned long board_type; /* index in the cardbase */
-	unsigned char *fb_base;	/* framebuffer memory base */
-	u32 fb_size;		/* framebuffer memory size */
-	unsigned char *p_fb;	/* physical address of frame buffer */
-	unsigned char *v_fb;	/* virtual address of frame buffer */
-	unsigned char *pIOBase;	/* physical address of registers region, must be rg_base or rg_base+PM2_REGS_SIZE depending on the host endianness */
-	unsigned char *vIOBase;	/* address of registers after ioremap() */
-	struct {
-		u8 transp;
-		u8 red;
-		u8 green;
-		u8 blue;
-	} palette[256];
-	union {
-#ifdef FBCON_HAS_CFB16
-		u16 cmap12[16]; /* RGBA 4444 */
-		u16 cmap15[16]; /* RGBA 5551 */
-		u16 cmap16[16]; /* RGBA 5650 */
-#endif
-#ifdef FBCON_HAS_CFB32
-		u32 cmap32[16];
-#endif
-	} cmap;
-	struct pm3fb_timings memt;
-};
-
-/* regular resolution database*/
-static struct {
-	char name[16];
-	struct pm3fb_par user_mode;
-} mode_base[] __initdata = {
-	{
-		"default-800x600", {
-	49500, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625,
-			    800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}}, {
-		"1024x768-74", {
-	78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
-			    806, 1024, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}}, {
-		"1024x768-74-32", {
-			78752, 1024, 768, 32, 128, 304, 1328, 1, 4, 38,
-			806, 1024, 0, 32,
-			PM3VideoControl_ENABLE |
-			PM3VideoControl_HSYNC_ACTIVE_HIGH
-			|
-			PM3VideoControl_VSYNC_ACTIVE_HIGH
-			| PM3VideoControl_PIXELSIZE_32BIT}},
-/* Generated mode : "1600x1024", for the SGI 1600SW flat panel*/
-	{
-		"SGI1600SW", {
-			108000, 1600, 1024, 16, 56, 104, 1704, 3, 6, 32,
-			1056, 1600, 0, 8,
-			PM3VideoControl_ENABLE|
-			PM3VideoControl_HSYNC_ACTIVE_LOW|PM3VideoControl_VSYNC_ACTIVE_LOW|
-			PM3VideoControl_PIXELSIZE_32BIT}}, 
-/* ##### auto-generated mode, by fbtimings2pm3 */
-/* Generated mode : "640x480-60" */
-	{
-		"640x480-60", {
-	25174, 640, 480, 16, 112, 160, 800, 10, 12, 45,
-			    525, 640, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-72" */
-	{
-		"640x480-72", {
-	31199, 640, 480, 24, 64, 192, 832, 9, 12, 40, 520,
-			    640, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-75" */
-	{
-		"640x480-75", {
-	31499, 640, 480, 16, 80, 200, 840, 1, 4, 20, 500,
-			    640, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-90" */
-	{
-		"640x480-90", {
-	39909, 640, 480, 32, 72, 192, 832, 25, 39, 53, 533,
-			    640, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "640x480-100" */
-	{
-		"640x480-100", {
-	44899, 640, 480, 32, 160, 208, 848, 22, 34, 51,
-			    531, 640, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-48-lace" */
-/* INTERLACED NOT SUPPORTED
-  {"800x600-48-lace", {35999, 800, 600, 80, 208, 264, 1064, 11, 23, 102, 702, 800, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, 
-   INTERLACED NOT SUPPORTED */
-/* Generated mode : "800x600-56" */
-	{
-		"800x600-56", {
-	35999, 800, 600, 24, 96, 224, 1024, 1, 3, 25, 625,
-			    800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-60" */
-	{
-		"800x600-60", {
-	40000, 800, 600, 40, 168, 256, 1056, 1, 5, 28, 628,
-			    800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-70" */
-	{
-		"800x600-70", {
-	44899, 800, 600, 24, 168, 208, 1008, 9, 21, 36,
-			    636, 800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-72" */
-	{
-		"800x600-72", {
-	50000, 800, 600, 56, 176, 240, 1040, 37, 43, 66,
-			    666, 800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-75" */
-	{
-		"800x600-75", {
-	49497, 800, 600, 16, 96, 256, 1056, 1, 4, 25, 625,
-			    800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-90" */
-	{
-		"800x600-90", {
-	56637, 800, 600, 8, 72, 192, 992, 8, 19, 35, 635,
-			    800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "800x600-100", from /etc/fb.modes */
-/* DISABLED, hsstart == 0
-	{
-		"800x600-100", {
-	67499, 800, 600, 0, 64, 280, 1080, 7, 11, 25, 625,
-			    800, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-*/
-/* Generated mode : "800x600-100", from ??? */
-	{
-		"800x600-100", {
-			69650, 800, 600, 64, 128, 288, 1088, 4, 10, 40, 640, 800, 0, 8,
-			PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW|
-			PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-43-lace" */
-/* INTERLACED NOT SUPPORTED
-  {"1024x768-43-lace", {44899, 1024, 768, 8, 184, 240, 1264, 1, 9, 49, 817, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, 
-   INTERLACED NOT SUPPORTED */
-/* Generated mode : "1024x768-60" */
-	{
-		"1024x768-60", {
-	64998, 1024, 768, 24, 160, 320, 1344, 3, 9, 38,
-			    806, 1024, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-70" */
-	{
-		"1024x768-70", {
-	74996, 1024, 768, 24, 160, 304, 1328, 3, 9, 38,
-			    806, 1024, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-72" */
-	{
-		"1024x768-72", {
-	74996, 10224, 768, 24, 160, 264, 10488, 3, 9, 38,
-			    806, 10224, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-75" */
-	{
-		"1024x768-75", {
-	78746, 1024, 768, 16, 112, 288, 1312, 1, 4, 32,
-			    800, 1024, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-90" */
-	{
-		"1024x768-90", {
-	100000, 1024, 768, 0, 96, 288, 1312, 21, 36, 77,
-			    845, 1024, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1024x768-100", from /etc/fb.modes */
-/* DISABLED, vsstart == 0
-	{
-		"1024x768-100", {
-	109998, 1024, 768, 0, 88, 368, 1392, 0, 8, 24, 792,
-			    1024, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-*/
-/* Generated mode : "1024x768-100", from ??? */
-	{
-		"1024x768-100", {
-			115500, 1024, 768, 32, 224, 416, 1440, 3, 13, 34, 802, 1024, 0, 8,
-			PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_LOW|
-			PM3VideoControl_VSYNC_ACTIVE_LOW|PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-43-lace" */
-/* INTERLACED NOT SUPPORTED
-  {"1152x864-43-lace", {64998, 1152, 864, 72, 200, 264, 1416, 78, 87, 191, 1055, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, 
-   INTERLACED NOT SUPPORTED */
-/* Generated mode : "1152x864-47-lace" */
-/* INTERLACED NOT SUPPORTED
-  {"1152x864-47-lace", {64998, 1152, 864, 88, 216, 296, 1448, 30, 39, 83, 947, 1152, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, 
-   INTERLACED NOT SUPPORTED */
-/* Generated mode : "1152x864-60" */
-	{
-		"1152x864-60", {
-	80000, 1152, 864, 64, 176, 304, 1456, 6, 11, 52,
-			    916, 1152, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-70" */
-	{
-		"1152x864-70", {
-	100000, 1152, 864, 40, 192, 360, 1512, 13, 24, 81,
-			    945, 1152, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-75" */
-	{
-		"1152x864-75", {
-	109998, 1152, 864, 24, 168, 312, 1464, 45, 53, 138,
-			    1002, 1152, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1152x864-80" */
-	{
-		"1152x864-80", {
-	109998, 1152, 864, 16, 128, 288, 1440, 30, 37, 94,
-			    958, 1152, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-43-lace" */
-/* INTERLACED NOT SUPPORTED
-  {"1280x1024-43-lace", {80000, 1024, 1024, 80, 160, 320, 1344, 50, 60, 125, 1149, 1024, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, 
-   INTERLACED NOT SUPPORTED */
-/* Generated mode : "1280x1024-47-lace" */
-/* INTERLACED NOT SUPPORTED
-  {"1280x1024-47-lace", {80000, 1280, 1024, 80, 160, 320, 1600, 1, 11, 29, 1053, 1280, 0, 8, PM3VideoControl_ENABLE|PM3VideoControl_HSYNC_ACTIVE_HIGH|PM3VideoControl_VSYNC_ACTIVE_HIGH|PM3VideoControl_PIXELSIZE_8BIT}}, 
-   INTERLACED NOT SUPPORTED */
-/* Generated mode : "1280x1024-60" */
-	{
-		"1280x1024-60", {
-	107991, 1280, 1024, 48, 160, 408, 1688, 1, 4, 42,
-			    1066, 1280, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-70" */
-	{
-		"1280x1024-70", {
-	125992, 1280, 1024, 80, 192, 408, 1688, 1, 6, 42,
-			    1066, 1280, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-74" */
-	{
-		"1280x1024-74", {
-	134989, 1280, 1024, 32, 176, 432, 1712, 0, 30, 40,
-			    1064, 1280, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1280x1024-75" */
-	{
-		"1280x1024-75", {
-	134989, 1280, 1024, 16, 160, 408, 1688, 1, 4, 42,
-			    1066, 1280, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_HIGH
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_HIGH
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1600x1200-60" */
-	{
-		"1600x1200-60", {
-	155981, 1600, 1200, 32, 192, 448, 2048, 10, 18, 70,
-			    1270, 1600, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1600x1200-66" */
-	{
-		"1600x1200-66", {
-	171998, 1600, 1200, 40, 176, 480, 2080, 3, 6, 53,
-			    1253, 1600, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* Generated mode : "1600x1200-76" */
-	{
-		"1600x1200-76", {
-	197980, 1600, 1200, 40, 176, 480, 2080, 3, 8, 50,
-			    1250, 1600, 0, 8,
-			    PM3VideoControl_ENABLE |
-			    PM3VideoControl_HSYNC_ACTIVE_LOW
-			    |
-			    PM3VideoControl_VSYNC_ACTIVE_LOW
-			    | PM3VideoControl_PIXELSIZE_8BIT}},
-/* ##### end of auto-generated mode */
-	{
-	"\0",}
-};
-
-/* more mandatory stuff (see skeletonfb.c + framebuffer driver HOWTO */
-static struct pm3fb_info fb_info[PM3_MAX_BOARD];
-static struct pm3fb_par current_par[PM3_MAX_BOARD];
-static int current_par_valid[PM3_MAX_BOARD];
-/* to allow explicit filtering of board */
-short bus[PM3_MAX_BOARD];
-short slot[PM3_MAX_BOARD];
-short func[PM3_MAX_BOARD];
-short disable[PM3_MAX_BOARD];
-short noaccel[PM3_MAX_BOARD];
-char fontn[PM3_MAX_BOARD][PM3_FONTNAME_SIZE];
-short depth[PM3_MAX_BOARD];
-short flatpanel[PM3_MAX_BOARD];
-static struct display disp[PM3_MAX_BOARD];
-static char g_options[PM3_OPTIONS_SIZE] __initdata = "pm3fb,dummy";
-short printtimings = 0;
-short forcesize[PM3_MAX_BOARD];
-
-/* ********************* */
-/* ***** prototype ***** */
-/* ********************* */
-/* card-specific */
-static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info);
-/* permedia3-specific */
-static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info);
-static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info);
-static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info);
-static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
-					unsigned long r);
-static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock,	/* In kHz units */
-					  unsigned long refclock,	/* In kHz units */
-					  unsigned char *prescale,	/* ClkPreScale */
-					  unsigned char *feedback,	/* ClkFeedBackScale */
-					  unsigned char *postscale
-					  /* ClkPostScale */ );
-static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc);
-static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b);
-static void pm3fb_common_init(struct pm3fb_info *l_fb_info);
-static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info,
-			  unsigned long depth, int v);
-static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info,
-			    unsigned long depth, int v);
-static void pm3fb_mapIO(struct pm3fb_info *l_fb_info);
-static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info);
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
-static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info);
-#endif
-static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info);
-static void pm3fb_write_mode(struct pm3fb_info *l_fb_info);
-static void pm3fb_read_mode(struct pm3fb_info *l_fb_info,
-			    struct pm3fb_par *curpar);
-static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info);
-/* accelerated permedia3-specific */
-#ifdef PM3FB_USE_ACCEL
-static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info);
-static void pm3fb_init_engine(struct pm3fb_info *l_fb_info);
-#ifdef FBCON_HAS_CFB32
-static void pm3fb_cfb32_clear(struct vc_data *conp,
-			      struct display *p,
-			      int sy, int sx, int height, int width);
-static void pm3fb_cfb32_clear_margins(struct vc_data *conp,
-				      struct display *p, int bottom_only);
-#endif /* FBCON_HAS_CFB32 */
-#ifdef FBCON_HAS_CFB16
-static void pm3fb_cfb16_clear(struct vc_data *conp,
-			      struct display *p,
-			      int sy, int sx, int height, int width);
-static void pm3fb_cfb16_clear_margins(struct vc_data *conp,
-				      struct display *p, int bottom_only);
-#endif /* FBCON_HAS_CFB16 */
-#ifdef FBCON_HAS_CFB8
-static void pm3fb_cfb8_clear(struct vc_data *conp,
-			     struct display *p,
-			     int sy, int sx, int height, int width);
-static void pm3fb_cfb8_clear_margins(struct vc_data *conp,
-				     struct display *p, int bottom_only);
-#endif /* FBCON_HAS_CFB8 */
-#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
-static void pm3fb_cfbX_bmove(struct display *p,
-			     int sy, int sx,
-			     int dy, int dx, int height, int width);
-static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p,
-			    int c, int yy, int xx);
-static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p,
-			     const unsigned short *s, int count, int yy,
-			     int xx);
-static void pm3fb_cfbX_revc(struct display *p, int xx, int yy);
-#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
-#endif /* PM3FB_USE_ACCEL */
-/* pre-init */
-static void pm3fb_mode_setup(char *mode, unsigned long board_num);
-static void pm3fb_pciid_setup(char *pciid, unsigned long board_num);
-static char *pm3fb_boardnum_setup(char *options, unsigned long *bn);
-static void pm3fb_real_setup(char *options);
-/* fbdev */
-static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix,
-			    const void *par, struct fb_info_gen *info);
-static int pm3fb_decode_var(const struct fb_var_screeninfo *var,
-			    void *par, struct fb_info_gen *info);
-static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d);
-static int pm3fb_encode_var(struct fb_var_screeninfo *var,
-			    const void *par, struct fb_info_gen *info);
-static void pm3fb_get_par(void *par, struct fb_info_gen *info);
-static void pm3fb_set_par(const void *par, struct fb_info_gen *info);
-static void pm3fb_set_color(struct pm3fb_info *l_fb_info,
-			    unsigned char regno, unsigned char r,
-			    unsigned char g, unsigned char b);
-static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info);
-static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info);
-static int pm3fb_blank(int blank_mode, struct fb_info_gen *info);
-static void pm3fb_set_disp(const void *par, struct display *disp,
-			   struct fb_info_gen *info);
-static void pm3fb_detect(void);
-static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
-			     struct fb_info_gen *info);
-static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg);
-
-
-/* the struct that hold them together */
-struct fbgen_hwswitch pm3fb_switch = {
-	pm3fb_detect, pm3fb_encode_fix, pm3fb_decode_var, pm3fb_encode_var,
-	pm3fb_get_par, pm3fb_set_par, pm3fb_getcolreg, 
-	pm3fb_pan_display, pm3fb_blank, pm3fb_set_disp
-};
-
-static struct fb_ops pm3fb_ops = {
-	.owner =	THIS_MODULE,
-	.fb_get_fix =	fbgen_get_fix,
-	.fb_get_var =	fbgen_get_var,
-	.fb_set_var =	fbgen_set_var,
-	.fb_get_cmap =	fbgen_get_cmap,
-	.fb_set_cmap =	fbgen_set_cmap,
-	.fb_setcolreg =	pm3fb_setcolreg,
-	.fb_pan_display =fbgen_pan_display,
-	.fb_blank =	fbgen_blank,
-	.fb_ioctl =	pm3fb_ioctl,
-};
-
-#ifdef PM3FB_USE_ACCEL
-#ifdef FBCON_HAS_CFB32
-static struct display_switch pm3fb_cfb32 = {
-	fbcon_cfb32_setup, pm3fb_cfbX_bmove, pm3fb_cfb32_clear,
-	pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc,
-	NULL /* cursor() */ , NULL /* set_font() */ ,
-	pm3fb_cfb32_clear_margins,
-	FONTWIDTHRANGE(1, 16)	/* true only if accelerated... */
-};
-#endif /* FBCON_HAS_CFB32 */
-#ifdef FBCON_HAS_CFB16
-static struct display_switch pm3fb_cfb16 = {
-	fbcon_cfb16_setup, pm3fb_cfbX_bmove, pm3fb_cfb16_clear,
-	pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc,
-	NULL /* cursor() */ , NULL /* set_font() */ ,
-	pm3fb_cfb16_clear_margins,
-	FONTWIDTHRANGE(1, 16)	/* true only if accelerated... */
-};
-#endif /* FBCON_HAS_CFB16 */
-#ifdef FBCON_HAS_CFB8
-static struct display_switch pm3fb_cfb8 = {
-	fbcon_cfb8_setup, pm3fb_cfbX_bmove, pm3fb_cfb8_clear,
-	pm3fb_cfbX_putc, pm3fb_cfbX_putcs, pm3fb_cfbX_revc,
-	NULL /* cursor() */ , NULL /* set_font() */ ,
-	pm3fb_cfb8_clear_margins,
-	FONTWIDTHRANGE(1, 16)	/* true only if accelerated... */
-};
-#endif /* FBCON_HAS_CFB8 */
-#endif /* PM3FB_USE_ACCEL */
-
-/* ****************************** */
-/* ***** card-specific data ***** */
-/* ****************************** */
-struct pm3fb_card_timings {
-	unsigned long memsize; /* 0 for last value (i.e. default) */
-	struct pm3fb_timings memt;
-};
-
-static struct pm3fb_card_timings t_FormacProFormance3[] = {
-	{ 16, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} },
-	{ 0, { 0x02e311b8, 0x06100205, 0x08000002, 0x00000079, 0x00000000} } /* from 16 MB PF3 */
-};
-
-static struct pm3fb_card_timings t_AppianJeronimo2000[] = {
-	{ 32, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} },
-	{ 0, { 0x02e311B8, 0x07424905, 0x0c000003, 0x00000061, 0x00000000} } /* from 32MB J2000 */
-};
-
-static struct pm3fb_card_timings t_3DLabsOxygenVX1[] = {
-	{ 32, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} },
-	{ 0, { 0x30e311b8, 0x08501204, 0x08000002, 0x0000006b, 0x00000000} } /* from 32MB VX1 */
-};
-
-static struct {
-		char cardname[32]; /* recognized card name */
-		u16 subvendor; /* subvendor of the card */
-		u16 subdevice; /* subdevice of the card */
-		u8  func; /* function of the card to which the extra init apply */
-		void (*specific_setup)(struct pm3fb_info *l_fb_info); /* card/func specific setup, done before _any_ FB access */
-	struct pm3fb_card_timings *c_memt; /* defauls timings for the boards */
-} cardbase[] = {
-	{ "Unknown Permedia3 board", 0xFFFF, 0xFFFF, 0xFF, NULL, NULL },
-	{ "Appian Jeronimo 2000 head 1", 0x1097, 0x3d32, 1, NULL,
-	  t_AppianJeronimo2000
-	},
-	{ "Appian Jeronimo 2000 head 2", 0x1097, 0x3d32, 2, pm3fb_j2000_setup,
-	  t_AppianJeronimo2000
-	},
-	{ "Formac ProFormance 3", PCI_VENDOR_ID_3DLABS, 0x000a, 0, NULL, /* Formac use 3DLabs ID ?!? */
-	  t_FormacProFormance3
-	},
-	{ "3DLabs Permedia3 Create!", PCI_VENDOR_ID_3DLABS, 0x0127, 0, NULL, NULL },
-	{ "3DLabs Oxygen VX1 PCI", PCI_VENDOR_ID_3DLABS, 0x0121, 0, NULL,
-	  t_3DLabsOxygenVX1
-	},
-	{ "3DLabs Oxygen VX1 AGP", PCI_VENDOR_ID_3DLABS, 0x0125, 0, NULL, NULL },
-	{ "3DLabs Oxygen VX1-16 AGP", PCI_VENDOR_ID_3DLABS, 0x0140, 0, NULL, NULL },
-	{ "3DLabs Oxygen VX1-1600SW PCI", PCI_VENDOR_ID_3DLABS, 0x0800, 0, NULL, NULL },
-	{ "\0", 0x0, 0x0, 0, NULL, NULL }
-};
-
-/* ********************************** */
-/* ***** card-specific function ***** */
-/* ********************************** */
-static void pm3fb_j2000_setup(struct pm3fb_info *l_fb_info)
-{       /* the appian j2000 require more initialization of the second head */
-	/* l_fb_info must point to the _second_ head of the J2000 */
-	
-	DTRACE;
-
-	l_fb_info->memt = t_AppianJeronimo2000[0].memt; /* 32 MB, first and only j2000 ? */
-	
-	pm3fb_write_memory_timings(l_fb_info);
+	return fb_readl(par->v_regs + off);
 }
 
-/* *************************************** */
-/* ***** permedia3-specific function ***** */
-/* *************************************** */
-static pm3fb_timing_result pm3fb_preserve_memory_timings(struct pm3fb_info *l_fb_info)
+static inline void PM3_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
 {
-	l_fb_info->memt.caps = PM3_READ_REG(PM3LocalMemCaps);
-	l_fb_info->memt.timings = PM3_READ_REG(PM3LocalMemTimings);
-	l_fb_info->memt.control = PM3_READ_REG(PM3LocalMemControl);
-	l_fb_info->memt.refresh = PM3_READ_REG(PM3LocalMemRefresh);
-	l_fb_info->memt.powerdown = PM3_READ_REG(PM3LocalMemPowerDown);
+	fb_writel(v, par->v_regs + off);
+}
 
-	if ((l_fb_info->memt.caps == PM3FB_UNKNOWN_TIMING_VALUE) ||
-	    (l_fb_info->memt.timings == PM3FB_UNKNOWN_TIMING_VALUE) ||
-	    (l_fb_info->memt.control == PM3FB_UNKNOWN_TIMING_VALUE) ||
-	    (l_fb_info->memt.refresh == PM3FB_UNKNOWN_TIMING_VALUE) ||
-	    (l_fb_info->memt.powerdown == PM3FB_UNKNOWN_TIMING_VALUE))
-	{
-		printk(KERN_ERR "pm3fb: invalid memory timings in permedia3 board #%ld\n", l_fb_info->board_num);
-		return(pm3fb_try_memory_timings(l_fb_info));
+static inline void PM3_WAIT(struct pm3_par *par, u32 n)
+{
+	while (PM3_READ_REG(par, PM3InFIFOSpace) < n);
+}
+
+static inline void PM3_SLOW_WRITE_REG(struct pm3_par *par, s32 off, u32 v)
+{
+	if (par->v_regs) {
+		mb();
+		PM3_WAIT(par, 1);
+		wmb();
+		PM3_WRITE_REG(par, off, v);
 	}
-	return(pm3fb_timing_ok);
 }
 
-static pm3fb_timing_result pm3fb_try_memory_timings(struct pm3fb_info *l_fb_info)
+static inline void PM3_SET_INDEX(struct pm3_par *par, unsigned index)
 {
-	if (cardbase[l_fb_info->board_type].c_memt)
-	{
-		int i = 0, done = 0;
-		while (!done)
-		{
-			if ((cardbase[l_fb_info->board_type].c_memt[i].memsize == l_fb_info->fb_size)
-			    || !(cardbase[l_fb_info->board_type].c_memt[i].memsize))
-			{ /* will use the 0-sized timings by default */
-				done = 1;
-				l_fb_info->memt = cardbase[l_fb_info->board_type].c_memt[i].memt;
-				printk(KERN_WARNING  "pm3fb: trying to use predefined memory timings for permedia3 board #%ld (%s, %ld MB)\n",
-				       l_fb_info->board_num,
-				       cardbase[l_fb_info->board_type].cardname,
-				       cardbase[l_fb_info->board_type].c_memt[i].memsize);
-				pm3fb_write_memory_timings(l_fb_info);
-				return(pm3fb_timing_retry);
-			}
-			i++;
-		}
-	} else
-		return(pm3fb_timing_problem);
-	return(pm3fb_timing_ok);
+	PM3_SLOW_WRITE_REG(par, PM3RD_IndexHigh, (index >> 8) & 0xff);
+	PM3_SLOW_WRITE_REG(par, PM3RD_IndexLow, index & 0xff);
 }
 
-static void pm3fb_write_memory_timings(struct pm3fb_info *l_fb_info)
+static inline void PM3_WRITE_DAC_REG(struct pm3_par *par, unsigned r, u8 v)
 {
-	unsigned char m, n, p;
-	unsigned long clockused;
-	
-	PM3_SLOW_WRITE_REG(PM3LocalMemCaps, l_fb_info->memt.caps);
-	PM3_SLOW_WRITE_REG(PM3LocalMemTimings, l_fb_info->memt.timings);
-	PM3_SLOW_WRITE_REG(PM3LocalMemControl, l_fb_info->memt.control);
-	PM3_SLOW_WRITE_REG(PM3LocalMemRefresh, l_fb_info->memt.refresh);
-	PM3_SLOW_WRITE_REG(PM3LocalMemPowerDown, l_fb_info->memt.powerdown);
-
-	clockused =
-	    pm3fb_CalculateClock(l_fb_info, 2 * 105000, PM3_REF_CLOCK, &m,
-				 &n, &p);
-
-	PM3_WRITE_DAC_REG(PM3RD_KClkPreScale, m);
-	PM3_WRITE_DAC_REG(PM3RD_KClkFeedbackScale, n);
-	PM3_WRITE_DAC_REG(PM3RD_KClkPostScale, p);
-	PM3_WRITE_DAC_REG(PM3RD_KClkControl,
-			  PM3RD_KClkControl_STATE_RUN |
-			  PM3RD_KClkControl_SOURCE_PLL |
-			  PM3RD_KClkControl_ENABLE);
-	PM3_WRITE_DAC_REG(PM3RD_MClkControl,
-			  PM3RD_MClkControl_STATE_RUN |
-			  PM3RD_MClkControl_SOURCE_KCLK |
-			  PM3RD_MClkControl_ENABLE);
-	PM3_WRITE_DAC_REG(PM3RD_SClkControl,
-			  PM3RD_SClkControl_STATE_RUN |
-			  PM3RD_SClkControl_SOURCE_PCLK |
-			  PM3RD_SClkControl_ENABLE);
+	PM3_SET_INDEX(par, r);
+	wmb();
+	PM3_WRITE_REG(par, PM3RD_IndexedData, v);
 }
 
-static unsigned long pm3fb_read_dac_reg(struct pm3fb_info *l_fb_info,
-					unsigned long r)
+static inline void pm3fb_set_color(struct pm3_par *par, unsigned char regno,
+			unsigned char r, unsigned char g, unsigned char b)
 {
-	DASSERT((l_fb_info->vIOBase != (unsigned char *) (-1)),
-		"l_fb_info->vIOBase mapped in read dac reg\n");
-	PM3_SET_INDEX(r);
-	mb();
-	return (PM3_READ_REG(PM3RD_IndexedData));
+	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteWriteAddress, regno);
+	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, r);
+	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, g);
+	PM3_SLOW_WRITE_REG(par, PM3RD_PaletteData, b);
+}
+
+static void pm3fb_clear_colormap(struct pm3_par *par,
+			unsigned char r, unsigned char g, unsigned char b)
+{
+	int i;
+
+	for (i = 0; i < 256 ; i++) /* fill color map with white */
+		pm3fb_set_color(par, i, r, g, b);
+
 }
 
 /* Calculating various clock parameter */
-static unsigned long pm3fb_CalculateClock(struct pm3fb_info *l_fb_info, unsigned long reqclock,	/* In kHz units */
-					  unsigned long refclock,	/* In kHz units */
-					  unsigned char *prescale,	/* ClkPreScale */
-					  unsigned char *feedback,	/* ClkFeedBackScale */
-					  unsigned char *postscale
-					  /* ClkPostScale */ )
+static void pm3fb_calculate_clock(unsigned long reqclock,
+				unsigned char *prescale,
+				unsigned char *feedback,
+				unsigned char *postscale)
 {
 	int f, pre, post;
 	unsigned long freq;
 	long freqerr = 1000;
-	unsigned long actualclock = 0;
-
-	DTRACE;
+	long currerr;
 
 	for (f = 1; f < 256; f++) {
 		for (pre = 1; pre < 256; pre++) {
 			for (post = 0; post < 5; post++) {
-				freq =
-				    ((2 * refclock * f) /
-				     (pre * (1 << post)));
-				if ((reqclock > freq - freqerr)
-				    && (reqclock < freq + freqerr)) {
-					freqerr =
-					    (reqclock >
-					     freq) ? reqclock -
-					    freq : freq - reqclock;
+				freq = ((2*PM3_REF_CLOCK * f) >> post) / pre;
+				currerr = (reqclock > freq)
+					? reqclock - freq
+					: freq - reqclock;
+				if (currerr < freqerr) {
+					freqerr = currerr;
 					*feedback = f;
 					*prescale = pre;
 					*postscale = post;
-					actualclock = freq;
 				}
 			}
 		}
 	}
-
-	return (actualclock);
 }
 
-static int pm3fb_Shiftbpp(struct pm3fb_info *l_fb_info,
-			  unsigned long depth, int v)
+static inline int pm3fb_shift_bpp(unsigned long depth, int v)
 {
-	DTRACE;
-	
 	switch (depth) {
 	case 8:
 		return (v >> 4);
@@ -918,181 +187,59 @@
 	case 32:
 		return (v >> 2);
 	}
-	DPRINTK(1, "Unsupported depth %ld\n", depth);
-	return (0);
-}
-
-static int pm3fb_Unshiftbpp(struct pm3fb_info *l_fb_info,
-			    unsigned long depth, int v)
-{
-	DTRACE;
-
-	switch (depth) {
-	case 8:
-		return (v << 4);
-	case 12:	
-	case 15:
-	case 16:
-		return (v << 3);
-	case 32:
-		return (v << 2);
-	}
-	DPRINTK(1, "Unsupported depth %ld\n", depth);
-	return (0);
-}
-
-static void pm3fb_mapIO(struct pm3fb_info *l_fb_info)
-{
-	DTRACE;
-
-	l_fb_info->vIOBase =
-	    ioremap((unsigned long) l_fb_info->pIOBase, PM3_REGS_SIZE);
-	l_fb_info->v_fb =
-	    ioremap((unsigned long) l_fb_info->p_fb, l_fb_info->fb_size);
-	DPRINTK(2, "IO mapping : IOBase %lx / %lx, fb %lx / %lx\n",
-		(unsigned long) l_fb_info->pIOBase,
-		(unsigned long) l_fb_info->vIOBase,
-		(unsigned long) l_fb_info->p_fb,
-		(unsigned long) l_fb_info->v_fb);
-}
-
-static void pm3fb_unmapIO(struct pm3fb_info *l_fb_info)
-{
-	DTRACE;
-
-	iounmap(l_fb_info->vIOBase);
-	iounmap(l_fb_info->v_fb);
-	l_fb_info->vIOBase = (unsigned char *) -1;
-	l_fb_info->v_fb = (unsigned char *) -1;
-}
-
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
-static void pm3fb_show_cur_mode(struct pm3fb_info *l_fb_info)
-{
-	DPRINTK(2, "PM3Aperture0: 0x%08x\n", PM3_READ_REG(PM3Aperture0));
-	DPRINTK(2, "PM3Aperture1: 0x%08x\n", PM3_READ_REG(PM3Aperture1));
-	DPRINTK(2, "PM3ByAperture1Mode: 0x%08x\n",
-		PM3_READ_REG(PM3ByAperture1Mode));
-	DPRINTK(2, "PM3ByAperture2Mode: 0x%08x\n",
-		PM3_READ_REG(PM3ByAperture2Mode));
-	DPRINTK(2, "PM3ChipConfig: 0x%08x\n", PM3_READ_REG(PM3ChipConfig));
-	DPRINTK(2, "PM3FIFODis: 0x%08x\n", PM3_READ_REG(PM3FIFODis));
-	DPRINTK(2, "PM3HTotal: 0x%08x\n", PM3_READ_REG(PM3HTotal));
-	DPRINTK(2, "PM3HbEnd: 0x%08x\n", PM3_READ_REG(PM3HbEnd));
-	DPRINTK(2, "PM3HgEnd: 0x%08x\n", PM3_READ_REG(PM3HgEnd));
-	DPRINTK(2, "PM3HsEnd: 0x%08x\n", PM3_READ_REG(PM3HsEnd));
-	DPRINTK(2, "PM3HsStart: 0x%08x\n", PM3_READ_REG(PM3HsStart));
-	DPRINTK(2, "PM3MemBypassWriteMask: 0x%08x\n",
-		PM3_READ_REG(PM3MemBypassWriteMask));
-	DPRINTK(2, "PM3RD_IndexControl: 0x%08x\n",
-		PM3_READ_REG(PM3RD_IndexControl));
-	DPRINTK(2, "PM3ScreenBase: 0x%08x\n", PM3_READ_REG(PM3ScreenBase));
-	DPRINTK(2, "PM3ScreenStride: 0x%08x\n",
-		PM3_READ_REG(PM3ScreenStride));
-	DPRINTK(2, "PM3VClkCtl: 0x%08x\n", PM3_READ_REG(PM3VClkCtl));
-	DPRINTK(2, "PM3VTotal: 0x%08x\n", PM3_READ_REG(PM3VTotal));
-	DPRINTK(2, "PM3VbEnd: 0x%08x\n", PM3_READ_REG(PM3VbEnd));
-	DPRINTK(2, "PM3VideoControl: 0x%08x\n",
-		PM3_READ_REG(PM3VideoControl));
-	DPRINTK(2, "PM3VsEnd: 0x%08x\n", PM3_READ_REG(PM3VsEnd));
-	DPRINTK(2, "PM3VsStart: 0x%08x\n", PM3_READ_REG(PM3VsStart));
-
-	DPRINTK(2, "PM3RD_ColorFormat: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_ColorFormat));
-	DPRINTK(2, "PM3RD_DACControl: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_DACControl));
-	DPRINTK(2, "PM3RD_DClk0FeedbackScale: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale));
-	DPRINTK(2, "PM3RD_DClk0PostScale: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_DClk0PostScale));
-	DPRINTK(2, "PM3RD_DClk0PreScale: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_DClk0PreScale));
-	DPRINTK(2, "[not set] PM3RD_IndexControl: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_IndexControl));
-	DPRINTK(2, "PM3RD_MiscControl: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_MiscControl));
-	DPRINTK(2, "PM3RD_PixelSize: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_PixelSize));
-	DPRINTK(2, "PM3RD_SyncControl: %ld\n",
-		PM3_READ_DAC_REG(PM3RD_SyncControl));
-}
-
-#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2) */
-static void pm3fb_show_cur_timing(struct pm3fb_info *l_fb_info)
-{
-	u16 subvendor, subdevice;
-
-	if ((!pci_read_config_word
-	     (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
-	    &&
-	    (!pci_read_config_word
-	     (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) {
-		/* well, nothing... */
-	} else {
-		subvendor = subdevice = (u16)-1;
-	}
-
-	printk(KERN_INFO "pm3fb: memory timings for board #%ld (subvendor: 0x%hx, subdevice: 0x%hx)\n", l_fb_info->board_num, subvendor, subdevice);
-	printk(KERN_INFO " PM3LocalMemCaps: 0x%08x\n",
-	       PM3_READ_REG(PM3LocalMemCaps));
-	printk(KERN_INFO " PM3LocalMemTimings: 0x%08x\n",
-	       PM3_READ_REG(PM3LocalMemTimings));
-	printk(KERN_INFO " PM3LocalMemControl: 0x%08x\n",
-	       PM3_READ_REG(PM3LocalMemControl));
-	printk(KERN_INFO " PM3LocalMemRefresh: 0x%08x\n",
-	       PM3_READ_REG(PM3LocalMemRefresh));
-	printk(KERN_INFO " PM3LocalMemPowerDown: 0x%08x\n",
-	       PM3_READ_REG(PM3LocalMemPowerDown));
+	DPRINTK("Unsupported depth %ld\n", depth);
+	return 0;
 }
 
 /* write the mode to registers */
-static void pm3fb_write_mode(struct pm3fb_info *l_fb_info)
+static void pm3fb_write_mode(struct fb_info *info)
 {
+	struct pm3_par *par = info->par;
 	char tempsync = 0x00, tempmisc = 0x00;
-	DTRACE;
+	const u32 hsstart = info->var.right_margin;
+	const u32 hsend = hsstart + info->var.hsync_len;
+	const u32 hbend = hsend + info->var.left_margin;
+	const u32 xres = (info->var.xres + 31) & ~31;
+	const u32 htotal = xres + hbend;
+	const u32 vsstart = info->var.lower_margin;
+	const u32 vsend = vsstart + info->var.vsync_len;
+	const u32 vbend = vsend + info->var.upper_margin;
+	const u32 vtotal = info->var.yres + vbend;
+	const u32 width = (info->var.xres_virtual + 7) & ~7;
 
-	PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xffffffff);
-	PM3_SLOW_WRITE_REG(PM3Aperture0, 0x00000000);
-	PM3_SLOW_WRITE_REG(PM3Aperture1, 0x00000000);
-	PM3_SLOW_WRITE_REG(PM3FIFODis, 0x00000007);
+	PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xffffffff);
+	PM3_SLOW_WRITE_REG(par, PM3Aperture0, 0x00000000);
+	PM3_SLOW_WRITE_REG(par, PM3Aperture1, 0x00000000);
+	PM3_SLOW_WRITE_REG(par, PM3FIFODis, 0x00000007);
 
-	PM3_SLOW_WRITE_REG(PM3HTotal,
-			   pm3fb_Shiftbpp(l_fb_info,
-					  l_fb_info->current_par->depth,
-					  l_fb_info->current_par->htotal -
-					  1));
-	PM3_SLOW_WRITE_REG(PM3HsEnd,
-			   pm3fb_Shiftbpp(l_fb_info,
-					  l_fb_info->current_par->depth,
-					  l_fb_info->current_par->hsend));
-	PM3_SLOW_WRITE_REG(PM3HsStart,
-			   pm3fb_Shiftbpp(l_fb_info,
-					  l_fb_info->current_par->depth,
-					  l_fb_info->current_par->
+	PM3_SLOW_WRITE_REG(par, PM3HTotal,
+			   pm3fb_shift_bpp(info->var.bits_per_pixel,
+					  htotal - 1));
+	PM3_SLOW_WRITE_REG(par, PM3HsEnd,
+			   pm3fb_shift_bpp(info->var.bits_per_pixel,
+					  hsend));
+	PM3_SLOW_WRITE_REG(par, PM3HsStart,
+			   pm3fb_shift_bpp(info->var.bits_per_pixel,
 					  hsstart));
-	PM3_SLOW_WRITE_REG(PM3HbEnd,
-			   pm3fb_Shiftbpp(l_fb_info,
-					  l_fb_info->current_par->depth,
-					  l_fb_info->current_par->hbend));
-	PM3_SLOW_WRITE_REG(PM3HgEnd,
-			   pm3fb_Shiftbpp(l_fb_info,
-					  l_fb_info->current_par->depth,
-					  l_fb_info->current_par->hbend));
-	PM3_SLOW_WRITE_REG(PM3ScreenStride,
-			   pm3fb_Shiftbpp(l_fb_info,
-					  l_fb_info->current_par->depth,
-					  l_fb_info->current_par->stride));
-	PM3_SLOW_WRITE_REG(PM3VTotal, l_fb_info->current_par->vtotal - 1);
-	PM3_SLOW_WRITE_REG(PM3VsEnd, l_fb_info->current_par->vsend - 1);
-	PM3_SLOW_WRITE_REG(PM3VsStart,
-			   l_fb_info->current_par->vsstart - 1);
-	PM3_SLOW_WRITE_REG(PM3VbEnd, l_fb_info->current_par->vbend);
+	PM3_SLOW_WRITE_REG(par, PM3HbEnd,
+			   pm3fb_shift_bpp(info->var.bits_per_pixel,
+					  hbend));
+	PM3_SLOW_WRITE_REG(par, PM3HgEnd,
+			   pm3fb_shift_bpp(info->var.bits_per_pixel,
+					  hbend));
+	PM3_SLOW_WRITE_REG(par, PM3ScreenStride,
+			   pm3fb_shift_bpp(info->var.bits_per_pixel,
+					  width));
+	PM3_SLOW_WRITE_REG(par, PM3VTotal, vtotal - 1);
+	PM3_SLOW_WRITE_REG(par, PM3VsEnd, vsend - 1);
+	PM3_SLOW_WRITE_REG(par, PM3VsStart, vsstart - 1);
+	PM3_SLOW_WRITE_REG(par, PM3VbEnd, vbend);
 
-	switch (l_fb_info->current_par->depth) {
+	switch (info->var.bits_per_pixel) {
 	case 8:
-		PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_8BIT);
-		PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_8BIT);
 		break;
 
@@ -1100,15 +247,15 @@
 	case 15:
 	case 16:
 #ifndef __BIG_ENDIAN
-		PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT);
-		PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT);
 #else
-		PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT |
 				   PM3ByApertureMode_BYTESWAP_BADC);
-		PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_16BIT |
 				   PM3ByApertureMode_BYTESWAP_BADC);
 #endif /* ! __BIG_ENDIAN */
@@ -1116,23 +263,23 @@
 
 	case 32:
 #ifndef __BIG_ENDIAN
-		PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT);
-		PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT);
 #else
-		PM3_SLOW_WRITE_REG(PM3ByAperture1Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture1Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT |
 				   PM3ByApertureMode_BYTESWAP_DCBA);
-		PM3_SLOW_WRITE_REG(PM3ByAperture2Mode,
+		PM3_SLOW_WRITE_REG(par, PM3ByAperture2Mode,
 				   PM3ByApertureMode_PIXELSIZE_32BIT |
 				   PM3ByApertureMode_BYTESWAP_DCBA);
 #endif /* ! __BIG_ENDIAN */
 		break;
 
 	default:
-		DPRINTK(1, "Unsupported depth %d\n",
-			l_fb_info->current_par->depth);
+		DPRINTK("Unsupported depth %d\n",
+			info->var.bits_per_pixel);
 		break;
 	}
 
@@ -1143,95 +290,86 @@
 	 * sync options in PM3RD_SyncControl.  --rmk
 	 */
 	{
-		unsigned int video = l_fb_info->current_par->video;
+		unsigned int video = par->video;
 
 		video &= ~(PM3VideoControl_HSYNC_MASK |
 			   PM3VideoControl_VSYNC_MASK);
 		video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
 			 PM3VideoControl_VSYNC_ACTIVE_HIGH;
-		PM3_SLOW_WRITE_REG(PM3VideoControl, video);
+		PM3_SLOW_WRITE_REG(par, PM3VideoControl, video);
 	}
-	PM3_SLOW_WRITE_REG(PM3VClkCtl,
-			   (PM3_READ_REG(PM3VClkCtl) & 0xFFFFFFFC));
-	PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base);
-	PM3_SLOW_WRITE_REG(PM3ChipConfig,
-			   (PM3_READ_REG(PM3ChipConfig) & 0xFFFFFFFD));
+	PM3_SLOW_WRITE_REG(par, PM3VClkCtl,
+			   (PM3_READ_REG(par, PM3VClkCtl) & 0xFFFFFFFC));
+	PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+	PM3_SLOW_WRITE_REG(par, PM3ChipConfig,
+			   (PM3_READ_REG(par, PM3ChipConfig) & 0xFFFFFFFD));
 
 	{
-		unsigned char m;	/* ClkPreScale */
-		unsigned char n;	/* ClkFeedBackScale */
-		unsigned char p;	/* ClkPostScale */
-		(void)pm3fb_CalculateClock(l_fb_info, l_fb_info->current_par->pixclock, PM3_REF_CLOCK, &m, &n, &p);
+		unsigned char uninitialized_var(m);	/* ClkPreScale */
+		unsigned char uninitialized_var(n);	/* ClkFeedBackScale */
+		unsigned char uninitialized_var(p);	/* ClkPostScale */
+		unsigned long pixclock = PICOS2KHZ(info->var.pixclock);
 
-		DPRINTK(2,
-			"Pixclock: %d, Pre: %d, Feedback: %d, Post: %d\n",
-			l_fb_info->current_par->pixclock, (int) m, (int) n,
-			(int) p);
+		(void)pm3fb_calculate_clock(pixclock, &m, &n, &p);
 
-		PM3_WRITE_DAC_REG(PM3RD_DClk0PreScale, m);
-		PM3_WRITE_DAC_REG(PM3RD_DClk0FeedbackScale, n);
-		PM3_WRITE_DAC_REG(PM3RD_DClk0PostScale, p);
+		DPRINTK("Pixclock: %ld, Pre: %d, Feedback: %d, Post: %d\n",
+			pixclock, (int) m, (int) n, (int) p);
+
+		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PreScale, m);
+		PM3_WRITE_DAC_REG(par, PM3RD_DClk0FeedbackScale, n);
+		PM3_WRITE_DAC_REG(par, PM3RD_DClk0PostScale, p);
 	}
 	/*
-	   PM3_WRITE_DAC_REG(PM3RD_IndexControl, 0x00);
+	   PM3_WRITE_DAC_REG(par, PM3RD_IndexControl, 0x00);
 	 */
 	/*
-	   PM3_SLOW_WRITE_REG(PM3RD_IndexControl, 0x00);
+	   PM3_SLOW_WRITE_REG(par, PM3RD_IndexControl, 0x00);
 	 */
-	if ((l_fb_info->current_par->video & PM3VideoControl_HSYNC_MASK) ==
+	if ((par->video & PM3VideoControl_HSYNC_MASK) ==
 	    PM3VideoControl_HSYNC_ACTIVE_HIGH)
 		tempsync |= PM3RD_SyncControl_HSYNC_ACTIVE_HIGH;
-	if ((l_fb_info->current_par->video & PM3VideoControl_VSYNC_MASK) ==
+	if ((par->video & PM3VideoControl_VSYNC_MASK) ==
 	    PM3VideoControl_VSYNC_ACTIVE_HIGH)
 		tempsync |= PM3RD_SyncControl_VSYNC_ACTIVE_HIGH;
-	
-	PM3_WRITE_DAC_REG(PM3RD_SyncControl, tempsync);
-	DPRINTK(2, "PM3RD_SyncControl: %d\n", tempsync);
-	
-	if (flatpanel[l_fb_info->board_num])
-	{
-		PM3_WRITE_DAC_REG(PM3RD_DACControl, PM3RD_DACControl_BLANK_PEDESTAL_ENABLE);
-		PM3_WAIT(2);
-		PM3_WRITE_REG(PM3VSConfiguration, 0x06);
-		PM3_WRITE_REG(0x5a00, 1 << 14); /* black magic... */
-		tempmisc = PM3RD_MiscControl_VSB_OUTPUT_ENABLE;
-	}
-	else
-		PM3_WRITE_DAC_REG(PM3RD_DACControl, 0x00);
 
-	switch (l_fb_info->current_par->depth) {
+	PM3_WRITE_DAC_REG(par, PM3RD_SyncControl, tempsync);
+	DPRINTK("PM3RD_SyncControl: %d\n", tempsync);
+
+	PM3_WRITE_DAC_REG(par, PM3RD_DACControl, 0x00);
+
+	switch (info->var.bits_per_pixel) {
 	case 8:
-		PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
 				  PM3RD_PixelSize_8_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
 				  PM3RD_ColorFormat_CI8_COLOR |
 				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
 		tempmisc |= PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
 		break;
 	case 12:
-		PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
 				  PM3RD_PixelSize_16_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
 				  PM3RD_ColorFormat_4444_COLOR |
 				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
 				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
 		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
 			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;		
+		break;
 	case 15:
-		PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
 				  PM3RD_PixelSize_16_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
 				  PM3RD_ColorFormat_5551_FRONT_COLOR |
 				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
 				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
 		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
 			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
-		break;		
+		break;
 	case 16:
-		PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
 				  PM3RD_PixelSize_16_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
 				  PM3RD_ColorFormat_565_FRONT_COLOR |
 				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW |
 				  PM3RD_ColorFormat_LINEAR_COLOR_EXT_ENABLE);
@@ -1239,1936 +377,280 @@
 			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
 		break;
 	case 32:
-		PM3_WRITE_DAC_REG(PM3RD_PixelSize,
+		PM3_WRITE_DAC_REG(par, PM3RD_PixelSize,
 				  PM3RD_PixelSize_32_BIT_PIXELS);
-		PM3_WRITE_DAC_REG(PM3RD_ColorFormat,
+		PM3_WRITE_DAC_REG(par, PM3RD_ColorFormat,
 				  PM3RD_ColorFormat_8888_COLOR |
 				  PM3RD_ColorFormat_COLOR_ORDER_BLUE_LOW);
 		tempmisc |= PM3RD_MiscControl_DIRECTCOLOR_ENABLE |
 			PM3RD_MiscControl_HIGHCOLOR_RES_ENABLE;
 		break;
 	}
-	PM3_WRITE_DAC_REG(PM3RD_MiscControl, tempmisc);
-	
-	PM3_SHOW_CUR_MODE;
+	PM3_WRITE_DAC_REG(par, PM3RD_MiscControl, tempmisc);
 }
 
-static void pm3fb_read_mode(struct pm3fb_info *l_fb_info,
-			    struct pm3fb_par *curpar)
+/*
+ * hardware independent functions
+ */
+int pm3fb_init(void);
+int pm3fb_setup(char*);
+
+static int pm3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	unsigned long pixsize1, pixsize2, clockused;
-	unsigned long pre, feedback, post;
+	u32 lpitch;
 
-	DTRACE;
-
-	clockused = PM3_READ_REG(PM3VClkCtl);
-
-	switch (clockused) {
-	case 3:
-		pre = PM3_READ_DAC_REG(PM3RD_DClk3PreScale);
-		feedback = PM3_READ_DAC_REG(PM3RD_DClk3FeedbackScale);
-		post = PM3_READ_DAC_REG(PM3RD_DClk3PostScale);
-
-		DPRINTK(2,
-			"DClk3 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
-			pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
-								feedback,
-								post));
-		break;
-	case 2:
-		pre = PM3_READ_DAC_REG(PM3RD_DClk2PreScale);
-		feedback = PM3_READ_DAC_REG(PM3RD_DClk2FeedbackScale);
-		post = PM3_READ_DAC_REG(PM3RD_DClk2PostScale);
-
-		DPRINTK(2,
-			"DClk2 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
-			pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
-								feedback,
-								post));
-		break;
-	case 1:
-		pre = PM3_READ_DAC_REG(PM3RD_DClk1PreScale);
-		feedback = PM3_READ_DAC_REG(PM3RD_DClk1FeedbackScale);
-		post = PM3_READ_DAC_REG(PM3RD_DClk1PostScale);
-
-		DPRINTK(2,
-			"DClk1 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
-			pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
-								feedback,
-								post));
-		break;
-	case 0:
-		pre = PM3_READ_DAC_REG(PM3RD_DClk0PreScale);
-		feedback = PM3_READ_DAC_REG(PM3RD_DClk0FeedbackScale);
-		post = PM3_READ_DAC_REG(PM3RD_DClk0PostScale);
-
-		DPRINTK(2,
-			"DClk0 parameter: Pre: %ld, Feedback: %ld, Post: %ld ; giving pixclock: %ld\n",
-			pre, feedback, post, PM3_SCALE_TO_CLOCK(pre,
-								feedback,
-								post));
-		break;
-	default:
-		pre = feedback = post = 0;
-		DPRINTK(1, "Unknowk D clock used : %ld\n", clockused);
-		break;
-	}
-
-	curpar->pixclock = PM3_SCALE_TO_CLOCK(pre, feedback, post);
-
-	pixsize1 =
-	    PM3ByApertureMode_PIXELSIZE_MASK &
-	    (PM3_READ_REG(PM3ByAperture1Mode));
-	pixsize2 =
-	    PM3ByApertureMode_PIXELSIZE_MASK &
-	    (PM3_READ_REG(PM3ByAperture2Mode));
-
-	DASSERT((pixsize1 == pixsize2),
-		"pixsize the same in both aperture\n");
-
-	if (pixsize1 & PM3ByApertureMode_PIXELSIZE_32BIT)
-		curpar->depth = 32;
-	else if (pixsize1 & PM3ByApertureMode_PIXELSIZE_16BIT)
-	{
-		curpar->depth = 16;
-	}
-	else
-		curpar->depth = 8;
-
-	/* not sure if I need to add one on the next ; it give better result with */
-	curpar->htotal =
-	    pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
-			     1 + PM3_READ_REG(PM3HTotal));
-	curpar->hsend =
-	    pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
-			     PM3_READ_REG(PM3HsEnd));
-	curpar->hsstart =
-	    pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
-			     PM3_READ_REG(PM3HsStart));
-	curpar->hbend =
-	    pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
-			     PM3_READ_REG(PM3HbEnd));
-
-	curpar->stride =
-	    pm3fb_Unshiftbpp(l_fb_info, curpar->depth,
-			     PM3_READ_REG(PM3ScreenStride));
-
-	curpar->vtotal = 1 + PM3_READ_REG(PM3VTotal);
-	curpar->vsend = 1 + PM3_READ_REG(PM3VsEnd);
-	curpar->vsstart = 1 + PM3_READ_REG(PM3VsStart);
-	curpar->vbend = PM3_READ_REG(PM3VbEnd);
-
-	curpar->video = PM3_READ_REG(PM3VideoControl);
-
-	curpar->base = PM3_READ_REG(PM3ScreenBase);
-	curpar->width = curpar->htotal - curpar->hbend; /* make virtual == displayed resolution */
-	curpar->height = curpar->vtotal - curpar->vbend;
-
-	DPRINTK(2, "Found : %d * %d, %d Khz, stride is %08x\n",
-		curpar->width, curpar->height, curpar->pixclock,
-		curpar->stride);
-}
-
-static unsigned long pm3fb_size_memory(struct pm3fb_info *l_fb_info)
-{
-	unsigned long memsize = 0, tempBypass, i, temp1, temp2;
-	u16 subvendor, subdevice;
-	pm3fb_timing_result ptr;
-
-	DTRACE;
-
-	l_fb_info->fb_size = 64 * 1024 * 1024;	/* pm3 aperture always 64 MB */
-	pm3fb_mapIO(l_fb_info);	/* temporary map IO */
-
-	DASSERT((l_fb_info->vIOBase != NULL),
-		"IO successfully mapped before mem detect\n");
-	DASSERT((l_fb_info->v_fb != NULL),
-		"FB successfully mapped before mem detect\n");
-
-	/* card-specific stuff, *before* accessing *any* FB memory */
-	if ((!pci_read_config_word
-	     (l_fb_info->dev, PCI_SUBSYSTEM_VENDOR_ID, &subvendor))
-	    &&
-	    (!pci_read_config_word
-	     (l_fb_info->dev, PCI_SUBSYSTEM_ID, &subdevice))) {
-		i = 0; l_fb_info->board_type = 0;
-		while ((cardbase[i].cardname[0]) && !(l_fb_info->board_type)) {
-			if ((cardbase[i].subvendor == subvendor) &&
-			    (cardbase[i].subdevice == subdevice) &&
-			    (cardbase[i].func == PCI_FUNC(l_fb_info->dev->devfn))) {
-				DPRINTK(2, "Card #%ld is an %s\n",
-					l_fb_info->board_num,
-					cardbase[i].cardname);
-				if (cardbase[i].specific_setup)
-					cardbase[i].specific_setup(l_fb_info);
-				l_fb_info->board_type = i;
-			}
-			i++;
-		}
-		if (!l_fb_info->board_type) {
-			DPRINTK(1, "Card #%ld is an unknown 0x%04x / 0x%04x\n",
-				l_fb_info->board_num, subvendor, subdevice);
-		}
-	} else {
-		printk(KERN_ERR "pm3fb: Error: pci_read_config_word failed, board #%ld\n",
-		       l_fb_info->board_num);
-	}
-
-	if (printtimings)
-		pm3fb_show_cur_timing(l_fb_info);
-	
-	/* card-specific setup is done, we preserve the final
-           memory timing for future reference */
-	if ((ptr = pm3fb_preserve_memory_timings(l_fb_info)) == pm3fb_timing_problem) { /* memory timings were wrong ! oops.... */
-		return(0);
-	}
-	
-	tempBypass = PM3_READ_REG(PM3MemBypassWriteMask);
-
-	DPRINTK(2, "PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
-
-	PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, 0xFFFFFFFF);
-
-	/* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
-	for (i = 0; i < 32; i++) {
-		fb_writel(i * 0x00345678,
-			  (l_fb_info->v_fb + (i * 1048576)));
-		mb();
-		temp1 = fb_readl((l_fb_info->v_fb + (i * 1048576)));
-
-		/* Let's check for wrapover, write will fail at 16MB boundary */
-		if (temp1 == (i * 0x00345678))
-			memsize = i;
-		else
-			break;
-	}
-
-	DPRINTK(2, "First detect pass already got %ld MB\n", memsize + 1);
-
-	if (memsize == i) {
-		for (i = 0; i < 32; i++) {
-			/* Clear first 32MB ; 0 is 0, no need to byteswap */
-			writel(0x0000000,
-			       (l_fb_info->v_fb + (i * 1048576)));
-			mb();
-		}
-
-		for (i = 32; i < 64; i++) {
-			fb_writel(i * 0x00345678,
-				  (l_fb_info->v_fb + (i * 1048576)));
-			mb();
-			temp1 =
-			    fb_readl((l_fb_info->v_fb + (i * 1048576)));
-			temp2 =
-			    fb_readl((l_fb_info->v_fb +
-				      ((i - 32) * 1048576)));
-			if ((temp1 == (i * 0x00345678)) && (temp2 == 0))	/* different value, different RAM... */
-				memsize = i;
-			else
-				break;
-		}
-	}
-
-	DPRINTK(2, "Second detect pass got %ld MB\n", memsize + 1);
-
-	PM3_SLOW_WRITE_REG(PM3MemBypassWriteMask, tempBypass);
-
-	pm3fb_unmapIO(l_fb_info);
-	memsize = 1048576 * (memsize + 1);
-
-	DPRINTK(2, "Returning 0x%08lx bytes\n", memsize);
-
-	if (forcesize[l_fb_info->board_num] && ((forcesize[l_fb_info->board_num] * 1048576) != memsize))
-	{
-		printk(KERN_WARNING "pm3fb: mismatch between probed (%ld MB) and specified (%hd MB) memory size, using SPECIFIED !\n", memsize, forcesize[l_fb_info->board_num]);
-		memsize = 1048576 * forcesize[l_fb_info->board_num];
-	}
-	
-	l_fb_info->fb_size = memsize;
-	
-	if (ptr == pm3fb_timing_retry)
-	{
-		printk(KERN_WARNING "pm3fb: retrying memory timings check");
-		if (pm3fb_try_memory_timings(l_fb_info) == pm3fb_timing_problem)
-			return(0);
-	}
-	
-	return (memsize);
-}
-
-static void pm3fb_clear_memory(struct pm3fb_info *l_fb_info, u32 cc)
-{
-	int i;
-
-	DTRACE;
-
-	for (i = 0; i < (l_fb_info->fb_size / sizeof(u32)) ; i++) /* clear entire FB memory to black */
-	{
-		fb_writel(cc, (l_fb_info->v_fb + (i * sizeof(u32))));
-	}
-}
-
-static void pm3fb_clear_colormap(struct pm3fb_info *l_fb_info, unsigned char r, unsigned char g, unsigned char b)
-{
-	int i;
-
-	DTRACE;
-
-	for (i = 0; i < 256 ; i++) /* fill color map with white */
-		pm3fb_set_color(l_fb_info, i, r, g, b);
-
-}
-
-/* common initialisation */
-static void pm3fb_common_init(struct pm3fb_info *l_fb_info)
-{
-	DTRACE;
-
-	DPRINTK(2, "Initializing board #%ld @ %lx\n", l_fb_info->board_num,
-		(unsigned long) l_fb_info);
-
-	strcpy(l_fb_info->gen.info.modename, permedia3_name);
-	disp[l_fb_info->board_num].scrollmode = 0;	/* SCROLL_YNOMOVE; *//* 0 means "let fbcon choose" */
-	l_fb_info->gen.parsize = sizeof(struct pm3fb_par);
-	l_fb_info->gen.info.changevar = NULL;
-	l_fb_info->gen.info.fbops = &pm3fb_ops;
-	l_fb_info->gen.info.disp = &(disp[l_fb_info->board_num]);
-	if (fontn[l_fb_info->board_num][0])
-		strcpy(l_fb_info->gen.info.fontname,
-		       fontn[l_fb_info->board_num]);
-	l_fb_info->gen.info.switch_con = &fbgen_switch;
-	l_fb_info->gen.info.updatevar = &fbgen_update_var;	/* */
-	l_fb_info->gen.info.flags = FBINFO_FLAG_DEFAULT;
-
-	pm3fb_mapIO(l_fb_info);
-
-	pm3fb_clear_memory(l_fb_info, 0);
-	pm3fb_clear_colormap(l_fb_info, 0, 0, 0);
-
-	(void) fbgen_get_var(&(disp[l_fb_info->board_num]).var, -1,
-			     &l_fb_info->gen.info);
-
-	if (depth[l_fb_info->board_num]) /* override mode-defined depth */
-	{
-		pm3fb_encode_depth(&(disp[l_fb_info->board_num]).var, depth[l_fb_info->board_num]);
-		(disp[l_fb_info->board_num]).var.bits_per_pixel = depth2bpp(depth[l_fb_info->board_num]);
-	}
-
-	(void) fbgen_do_set_var(&(disp[l_fb_info->board_num]).var, 1,
-				&l_fb_info->gen);
-
-	fbgen_set_disp(-1, &l_fb_info->gen);
-
-	do_install_cmap(0, &l_fb_info->gen.info);
-
-	if (register_framebuffer(&l_fb_info->gen.info) < 0) {
-		DPRINTK(1, "Couldn't register framebuffer\n");
-		return;
-	}
-
-	PM3_WRITE_DAC_REG(PM3RD_CursorMode,
-			  PM3RD_CursorMode_CURSOR_DISABLE);
-	
-	PM3_SHOW_CUR_MODE;
-	
-	pm3fb_write_mode(l_fb_info);
-	
-	printk("fb%d: %s, using %uK of video memory (%s)\n",
-	       l_fb_info->gen.info.node,
-	       permedia3_name, (u32) (l_fb_info->fb_size >> 10),
-	       cardbase[l_fb_info->board_type].cardname);
-}
-
-/* **************************************************** */
-/* ***** accelerated permedia3-specific functions ***** */
-/* **************************************************** */
-#ifdef PM3FB_USE_ACCEL
-static void pm3fb_wait_pm3(struct pm3fb_info *l_fb_info)
-{
-	DTRACE;
-
-	PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync);
-	PM3_SLOW_WRITE_REG(PM3Sync, 0);
-	mb();
-	do {
-		while ((PM3_READ_REG(PM3OutFIFOWords)) == 0);
-		rmb();
-	} while ((PM3_READ_REG(PM3OutputFifo)) != PM3Sync_Tag);
-}
-
-static void pm3fb_init_engine(struct pm3fb_info *l_fb_info)
-{
-	PM3_SLOW_WRITE_REG(PM3FilterMode, PM3FilterModeSync);
-	PM3_SLOW_WRITE_REG(PM3StatisticMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3DeltaMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3RasterizerMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3ScissorMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3LineStippleMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3AreaStippleMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3GIDMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3DepthMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3StencilMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3StencilData, 0x0);
-	PM3_SLOW_WRITE_REG(PM3ColorDDAMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureCoordMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureIndexMode0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureIndexMode1, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureReadMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3LUTMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureFilterMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureCompositeMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureApplicationMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode1, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode1, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureCompositeColorMode0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3TextureCompositeAlphaMode0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FogMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3ChromaTestMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3AlphaTestMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3AntialiasMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3YUVMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3AlphaBlendColorMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3AlphaBlendAlphaMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3DitherMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3LogicalOpMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3RouterMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3Window, 0x0);
-
-	PM3_SLOW_WRITE_REG(PM3Config2D, 0x0);
-
-	PM3_SLOW_WRITE_REG(PM3SpanColorMask, 0xffffffff);
-
-	PM3_SLOW_WRITE_REG(PM3XBias, 0x0);
-	PM3_SLOW_WRITE_REG(PM3YBias, 0x0);
-	PM3_SLOW_WRITE_REG(PM3DeltaControl, 0x0);
-
-	PM3_SLOW_WRITE_REG(PM3BitMaskPattern, 0xffffffff);
-
-	PM3_SLOW_WRITE_REG(PM3FBDestReadEnables,
-			   PM3FBDestReadEnables_E(0xff) |
-			   PM3FBDestReadEnables_R(0xff) |
-			   PM3FBDestReadEnables_ReferenceAlpha(0xff));
-	PM3_SLOW_WRITE_REG(PM3FBDestReadBufferAddr0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FBDestReadBufferOffset0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FBDestReadBufferWidth0,
-			   PM3FBDestReadBufferWidth_Width(l_fb_info->
-							  current_par->
-							  width));
-
-	PM3_SLOW_WRITE_REG(PM3FBDestReadMode,
-			   PM3FBDestReadMode_ReadEnable |
-			   PM3FBDestReadMode_Enable0);
-	PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferAddr, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferOffset, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FBSourceReadBufferWidth,
-			   PM3FBSourceReadBufferWidth_Width(l_fb_info->
-							    current_par->
-							    width));
-	PM3_SLOW_WRITE_REG(PM3FBSourceReadMode,
-			   PM3FBSourceReadMode_Blocking |
-			   PM3FBSourceReadMode_ReadEnable);
-
-	{
-		unsigned long rm = 1;
-		switch (l_fb_info->current_par->depth) {
-		case 8:
-			PM3_SLOW_WRITE_REG(PM3PixelSize,
-					   PM3PixelSize_GLOBAL_8BIT);
-			break;
-		case 12:
-		case 15:
-		case 16:
-			PM3_SLOW_WRITE_REG(PM3PixelSize,
-					   PM3PixelSize_GLOBAL_16BIT);
-			break;
-		case 32:
-			PM3_SLOW_WRITE_REG(PM3PixelSize,
-					   PM3PixelSize_GLOBAL_32BIT);
-			break;
-		default:
-			DPRINTK(1, "Unsupported depth %d\n",
-				l_fb_info->current_par->depth);
-			break;
-		}
-		PM3_SLOW_WRITE_REG(PM3RasterizerMode, rm);
-	}
-
-	PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xffffffff);
-	PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xffffffff);
-	PM3_SLOW_WRITE_REG(PM3FBWriteMode,
-			   PM3FBWriteMode_WriteEnable |
-			   PM3FBWriteMode_OpaqueSpan |
-			   PM3FBWriteMode_Enable0);
-	PM3_SLOW_WRITE_REG(PM3FBWriteBufferAddr0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FBWriteBufferOffset0, 0x0);
-	PM3_SLOW_WRITE_REG(PM3FBWriteBufferWidth0,
-			   PM3FBWriteBufferWidth_Width(l_fb_info->
-						       current_par->
-						       width));
-
-	PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 0x0);
-	{
-		unsigned long sofb = (8UL * l_fb_info->fb_size) /
-			((depth2bpp(l_fb_info->current_par->depth))
-			 * l_fb_info->current_par->width);	/* size in lines of FB */
-		if (sofb > 4095)
-			PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, 4095);
-		else
-			PM3_SLOW_WRITE_REG(PM3SizeOfFramebuffer, sofb);
-		
-		switch (l_fb_info->current_par->depth) {
-		case 8:
-			PM3_SLOW_WRITE_REG(PM3DitherMode,
-					   (1 << 10) | (2 << 3));
-			break;
-		case 12:
-		case 15:
-		case 16:
-			PM3_SLOW_WRITE_REG(PM3DitherMode,
-					   (1 << 10) | (1 << 3));
-			break;
-		case 32:
-			PM3_SLOW_WRITE_REG(PM3DitherMode,
-					   (1 << 10) | (0 << 3));
-			break;
-		default:
-			DPRINTK(1, "Unsupported depth %d\n",
-				l_fb_info->current_par->depth);
-			break;
-		}
-	}
-
-	PM3_SLOW_WRITE_REG(PM3dXDom, 0x0);
-	PM3_SLOW_WRITE_REG(PM3dXSub, 0x0);
-	PM3_SLOW_WRITE_REG(PM3dY, (1 << 16));
-	PM3_SLOW_WRITE_REG(PM3StartXDom, 0x0);
-	PM3_SLOW_WRITE_REG(PM3StartXSub, 0x0);
-	PM3_SLOW_WRITE_REG(PM3StartY, 0x0);
-	PM3_SLOW_WRITE_REG(PM3Count, 0x0);
-	
-/* Disable LocalBuffer. better safe than sorry */
-	PM3_SLOW_WRITE_REG(PM3LBDestReadMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3LBDestReadEnables, 0x0);
-	PM3_SLOW_WRITE_REG(PM3LBSourceReadMode, 0x0);
-	PM3_SLOW_WRITE_REG(PM3LBWriteMode, 0x0);
-	
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-#ifdef FBCON_HAS_CFB32
-static void pm3fb_cfb32_clear(struct vc_data *conp,
-			      struct display *p,
-			      int sy, int sx, int height, int width)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	u32 c;
-
-	DTRACE;
-
-	sx = sx * fontwidth(p);
-	width = width * fontwidth(p);
-	sy = sy * fontheight(p);
-	height = height * fontheight(p);
-	c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-
-	/* block fills in 32bpp are hard, but in low res (width <= 1600 :-)
-	   we can use 16bpp operations, but not if NoWriteMask is on (SDRAM)  */
-	if ((l_fb_info->current_par->width > 1600) ||
-	    (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)) {
-		PM3_WAIT(4);
-
-		PM3_WRITE_REG(PM3Config2D,
-					  PM3Config2D_UseConstantSource |
-					  PM3Config2D_ForegroundROPEnable |
-					  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-					  PM3Config2D_FBWriteEnable);
-
-		PM3_WRITE_REG(PM3ForegroundColor, c);
-
-		PM3_WRITE_REG(PM3RectanglePosition,
-			      (PM3RectanglePosition_XOffset(sx)) |
-			      (PM3RectanglePosition_YOffset(sy)));
-
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      PM3Render2D_SpanOperation |
-			      (PM3Render2D_Width(width)) |
-			      (PM3Render2D_Height(height)));
-	} else {
-		PM3_WAIT(8);
-
-		PM3_WRITE_REG(PM3FBBlockColor, c);
-
-		PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_16BIT);
-
-		PM3_WRITE_REG(PM3FBWriteBufferWidth0,
-			      PM3FBWriteBufferWidth_Width(l_fb_info->
-							  current_par->
-							  width << 1));
-
-		PM3_WRITE_REG(PM3Config2D,
-					  PM3Config2D_UseConstantSource |
-					  PM3Config2D_ForegroundROPEnable |
-					  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-					  PM3Config2D_FBWriteEnable);
-
-		PM3_WRITE_REG(PM3RectanglePosition,
-			      (PM3RectanglePosition_XOffset(sx << 1)) |
-			      (PM3RectanglePosition_YOffset(sy)));
-
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      (PM3Render2D_Width(width << 1)) |
-			      (PM3Render2D_Height(height)));
-
-		PM3_WRITE_REG(PM3FBWriteBufferWidth0,
-			      PM3FBWriteBufferWidth_Width(l_fb_info->
-							  current_par->
-							  width));
-
-		PM3_WRITE_REG(PM3PixelSize, PM3PixelSize_GLOBAL_32BIT);
-	}
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfb32_clear_margins(struct vc_data *conp,
-				      struct display *p, int bottom_only)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	int sx, sy;
-	u32 c;
-
-	DTRACE;
-
-	sx = conp->vc_cols * fontwidth(p);	/* right margin */
-	sy = conp->vc_rows * fontheight(p);	/* bottom margin */
-	c = ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-
-	if (!bottom_only) {	/* right margin top->bottom */
-		PM3_WAIT(4);
-
-		PM3_WRITE_REG(PM3Config2D,
-					  PM3Config2D_UseConstantSource |
-					  PM3Config2D_ForegroundROPEnable |
-					  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-					  PM3Config2D_FBWriteEnable);
-
-		PM3_WRITE_REG(PM3ForegroundColor, c);
-
-		PM3_WRITE_REG(PM3RectanglePosition,
-			      (PM3RectanglePosition_XOffset
-			       (p->var.xoffset +
-				sx)) | (PM3RectanglePosition_YOffset(p->
-								     var.
-								     yoffset)));
-
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      PM3Render2D_SpanOperation |
-			      (PM3Render2D_Width(p->var.xres - sx)) |
-			      (PM3Render2D_Height(p->var.yres)));
-	}
-
-	/* bottom margin left -> right */
-	PM3_WAIT(4);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(PM3ForegroundColor, c);
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(p->var.xoffset)) |
-		      (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
-
-	PM3_WRITE_REG(PM3Render2D,
-		      PM3Render2D_XPositive |
-		      PM3Render2D_YPositive |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      (PM3Render2D_Width(p->var.xres)) |
-		      (PM3Render2D_Height(p->var.yres - sy)));
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-#endif /* FBCON_HAS_CFB32 */
-#ifdef FBCON_HAS_CFB16
-static void pm3fb_cfb16_clear(struct vc_data *conp,
-			      struct display *p,
-			      int sy, int sx, int height, int width)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	u32 c;
-
-	DTRACE;
-
-	sx = sx * fontwidth(p);
-	width = width * fontwidth(p);
-	sy = sy * fontheight(p);
-	height = height * fontheight(p);
-	c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-	c = c | (c << 16);
-
-	PM3_WAIT(4);
-
-	if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-		PM3_WRITE_REG(PM3ForegroundColor, c);
-	else
-		PM3_WRITE_REG(PM3FBBlockColor, c);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(sx)) |
-		      (PM3RectanglePosition_YOffset(sy)));
-	
-	if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      PM3Render2D_SpanOperation |
-			      (PM3Render2D_Width(width)) |
-			      (PM3Render2D_Height(height)));
-	else
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      (PM3Render2D_Width(width)) |
-			      (PM3Render2D_Height(height)));
-	
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfb16_clear_margins(struct vc_data *conp,
-				      struct display *p, int bottom_only)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	int sx, sy;
-	u32 c;
-
-	DTRACE;
-
-	sx = conp->vc_cols * fontwidth(p);	/* right margin */
-	sy = conp->vc_rows * fontheight(p);	/* bottom margin */
-	c = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
-	c = c | (c << 16);
-
-	if (!bottom_only) {	/* right margin top->bottom */
-		PM3_WAIT(4);
-
-		PM3_WRITE_REG(PM3Config2D,
-					  PM3Config2D_UseConstantSource |
-					  PM3Config2D_ForegroundROPEnable |
-					  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-					  PM3Config2D_FBWriteEnable);
-		
-		if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-			PM3_WRITE_REG(PM3ForegroundColor, c);
-		else
-			PM3_WRITE_REG(PM3FBBlockColor, c);
-		
-		PM3_WRITE_REG(PM3RectanglePosition,
-			      (PM3RectanglePosition_XOffset
-			       (p->var.xoffset +
-				sx)) | (PM3RectanglePosition_YOffset(p->
-								     var.
-								     yoffset)));
-		if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-			PM3_WRITE_REG(PM3Render2D,
-				      PM3Render2D_XPositive |
-				      PM3Render2D_YPositive |
-				      PM3Render2D_Operation_Normal |
-				      PM3Render2D_SpanOperation |
-				      (PM3Render2D_Width(p->var.xres - sx)) |
-				      (PM3Render2D_Height(p->var.yres)));
-		else
-			PM3_WRITE_REG(PM3Render2D,
-				      PM3Render2D_XPositive |
-				      PM3Render2D_YPositive |
-				      PM3Render2D_Operation_Normal |
-				      (PM3Render2D_Width(p->var.xres - sx)) |
-				      (PM3Render2D_Height(p->var.yres)));
-	}
-	
-	/* bottom margin left -> right */
-	PM3_WAIT(4);
-	
-	PM3_WRITE_REG(PM3Config2D,
-		      PM3Config2D_UseConstantSource |
-		      PM3Config2D_ForegroundROPEnable |
-		      (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-		      PM3Config2D_FBWriteEnable);
-	
-	if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-		PM3_WRITE_REG(PM3ForegroundColor, c);
-	else
-		PM3_WRITE_REG(PM3FBBlockColor, c);
-	
-	
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(p->var.xoffset)) |
-		      (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
-	
-	if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      PM3Render2D_SpanOperation |
-			      (PM3Render2D_Width(p->var.xres)) |
-			      (PM3Render2D_Height(p->var.yres - sy)));
-	else
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      (PM3Render2D_Width(p->var.xres)) |
-			      (PM3Render2D_Height(p->var.yres - sy)));
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-#endif /* FBCON_HAS_CFB16 */
-#ifdef FBCON_HAS_CFB8
-static void pm3fb_cfb8_clear(struct vc_data *conp,
-			     struct display *p,
-			     int sy, int sx, int height, int width)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	u32 c;
-
-	DTRACE;
-
-	sx = sx * fontwidth(p);
-	width = width * fontwidth(p);
-	sy = sy * fontheight(p);
-	height = height * fontheight(p);
-
-	c = attr_bgcol_ec(p, conp);
-	c |= c << 8;
-	c |= c << 16;
-
-	PM3_WAIT(4);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(PM3ForegroundColor, c);
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(sx)) |
-		      (PM3RectanglePosition_YOffset(sy)));
-
-	PM3_WRITE_REG(PM3Render2D,
-		      PM3Render2D_XPositive |
-		      PM3Render2D_YPositive |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      (PM3Render2D_Width(width)) |
-		      (PM3Render2D_Height(height)));
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfb8_clear_margins(struct vc_data *conp,
-				     struct display *p, int bottom_only)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	int sx, sy;
-	u32 c;
-
-	DTRACE;
-
-	sx = conp->vc_cols * fontwidth(p);	/* right margin */
-	sy = conp->vc_rows * fontheight(p);	/* bottom margin */
-	c = attr_bgcol_ec(p, conp);
-	c |= c << 8;
-	c |= c << 16;
-
-	if (!bottom_only) {	/* right margin top->bottom */
-		PM3_WAIT(4);
-
-		PM3_WRITE_REG(PM3Config2D,
-					  PM3Config2D_UseConstantSource |
-					  PM3Config2D_ForegroundROPEnable |
-					  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-					  PM3Config2D_FBWriteEnable);
-
-		PM3_WRITE_REG(PM3ForegroundColor, c);
-
-		PM3_WRITE_REG(PM3RectanglePosition,
-			      (PM3RectanglePosition_XOffset
-			       (p->var.xoffset +
-				sx)) | (PM3RectanglePosition_YOffset(p->
-								     var.
-								     yoffset)));
-
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      PM3Render2D_SpanOperation |
-			      (PM3Render2D_Width(p->var.xres - sx)) |
-			      (PM3Render2D_Height(p->var.yres)));
-	}
-
-	/* bottom margin left -> right */
-	PM3_WAIT(4);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(PM3ForegroundColor, c);
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(p->var.xoffset)) |
-		      (PM3RectanglePosition_YOffset(p->var.yoffset + sy)));
-
-	PM3_WRITE_REG(PM3Render2D,
-		      PM3Render2D_XPositive |
-		      PM3Render2D_YPositive |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      (PM3Render2D_Width(p->var.xres)) |
-		      (PM3Render2D_Height(p->var.yres - sy)));
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-#endif /* FBCON_HAS_CFB8 */
-#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
-static void pm3fb_cfbX_bmove(struct display *p,
-			     int sy, int sx,
-			     int dy, int dx, int height, int width)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	int x_align, o_x, o_y;
-
-	DTRACE;
-
-	sx = sx * fontwidth(p);
-	dx = dx * fontwidth(p);
-	width = width * fontwidth(p);
-	sy = sy * fontheight(p);
-	dy = dy * fontheight(p);
-	height = height * fontheight(p);
-
-	o_x = sx - dx;		/*(sx > dx ) ? (sx - dx) : (dx - sx); */
-	o_y = sy - dy;		/*(sy > dy ) ? (sy - dy) : (dy - sy); */
-
-	x_align = (sx & 0x1f);
-
-	PM3_WAIT(6);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UserScissorEnable |
-				  PM3Config2D_ForegroundROPEnable |
-				  PM3Config2D_Blocking |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(PM3ScissorMinXY,
-		      ((dy & 0x0fff) << 16) | (dx & 0x0fff));
-	PM3_WRITE_REG(PM3ScissorMaxXY,
-				  (((dy + height) & 0x0fff) << 16) |
-				  ((dx + width) & 0x0fff));
-
-	PM3_WRITE_REG(PM3FBSourceReadBufferOffset,
-		      PM3FBSourceReadBufferOffset_XOffset(o_x) |
-		      PM3FBSourceReadBufferOffset_YOffset(o_y));
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(dx - x_align)) |
-		      (PM3RectanglePosition_YOffset(dy)));
-
-	PM3_WRITE_REG(PM3Render2D,
-		      ((sx > dx) ? PM3Render2D_XPositive : 0) |
-		      ((sy > dy) ? PM3Render2D_YPositive : 0) |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      PM3Render2D_FBSourceReadEnable |
-		      (PM3Render2D_Width(width + x_align)) |
-		      (PM3Render2D_Height(height)));
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfbX_putc(struct vc_data *conp, struct display *p,
-			    int c, int yy, int xx)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
-	u32 fgx, bgx, ldat;
-	int sx, sy, i;
-
-	DTRACE;
-
-	if (l_fb_info->current_par->depth == 8)
-		fgx = attr_fgcol(p, c);
-	else if (depth2bpp(l_fb_info->current_par->depth) == 16)
-		fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, c)];
-	else
-		fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, c)];
-
-	PM3_COLOR(fgx);
-
-	if (l_fb_info->current_par->depth == 8)
-		bgx = attr_bgcol(p, c);
-	else if (depth2bpp(l_fb_info->current_par->depth) == 16)
-		bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, c)];
-	else
-		bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, c)];
-
-	PM3_COLOR(bgx);
-
-	PM3_WAIT(4);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable | PM3Config2D_OpaqueSpan);
-
-	PM3_WRITE_REG(PM3ForegroundColor, fgx);
-	PM3_WRITE_REG(PM3FillBackgroundColor, bgx);
-
-	/* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */
-	/* and 16 bits for fontwidth <= 16 */
-	/* same in _putcs, same for Y and fontheight */
-	if (fontwidth(p) <= 8)
-		asx = 2;
-	else if (fontwidth(p) <= 16)
-		asx = 3;	/* look OK */
-	if (fontheight(p) <= 8)
-		asy = 2;
-	else if (fontheight(p) <= 16)
-		asy = 3;	/* look OK */
-	else if (fontheight(p) <= 32)
-		asy = 4;	/* look OK */
-
-	sx = xx * fontwidth(p);
-	sy = yy * fontheight(p);
-
-	if (fontwidth(p) <= 8)
-		o_x = (8 - (sx & 0x7)) & 0x7;
-	else if (fontwidth(p) <= 16)
-		o_x = (16 - (sx & 0xF)) & 0xF;
-	if (fontheight(p) <= 8)
-		o_y = (8 - (sy & 0x7)) & 0x7;
-	else if (fontheight(p) <= 16)
-		o_y = (16 - (sy & 0xF)) & 0xF;
-	else if (fontheight(p) <= 32)
-		o_y = (32 - (sy & 0x1F)) & 0x1F;
-
-	PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) |	/* x_offset, y_offset in pattern */
-		      (1 << 18) |	/* BE */
-		      1 | (asx << 1) | (asy << 4) |	/* address select x/y */
-		      (1 << 20));	/* OpaqueSpan */
-
-	if (fontwidth(p) <= 8) {
-		cdat = p->fontdata + (c & p->charmask) * fontheight(p);
-	} else {
-		cdat =
-		    p->fontdata +
-		    ((c & p->charmask) * (fontheight(p) << 1));
-	}
-
-	PM3_WAIT(2 + fontheight(p));
-
-	for (i = 0; i < fontheight(p); i++) {	/* assume fontheight <= 32 */
-		if (fontwidth(p) <= 8) {
-			ldat = *cdat++;
-		} else {	/* assume fontwidth <= 16 ATM */
-
-			ldat = ((*cdat++) << 8);
-			ldat |= *cdat++;
-		}
-		PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat);
-	}
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(sx)) |
-		      (PM3RectanglePosition_YOffset(sy)));
-
-	PM3_WRITE_REG(PM3Render2D,
-		      PM3Render2D_AreaStippleEnable |
-		      PM3Render2D_XPositive |
-		      PM3Render2D_YPositive |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      (PM3Render2D_Width(fontwidth(p))) |
-		      (PM3Render2D_Height(fontheight(p))));
-
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfbX_putcs(struct vc_data *conp, struct display *p,
-			     const unsigned short *s, int count, int yy,
-			     int xx)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-	u8 *cdat, asx = 0, asy = 0, o_x = 0, o_y = 0;
-	u32 fgx, bgx, ldat;
-	int sx, sy, i, j;
-	u16 sc;
-
-	DTRACE;
-
-	sc = scr_readw(s);
-	if (l_fb_info->current_par->depth == 8)
-		fgx = attr_fgcol(p, sc);
-	else if (depth2bpp(l_fb_info->current_par->depth) == 16)
-		fgx = ((u16 *) p->dispsw_data)[attr_fgcol(p, sc)];
-	else
-		fgx = ((u32 *) p->dispsw_data)[attr_fgcol(p, sc)];
-	
-	PM3_COLOR(fgx);
-	
-	if (l_fb_info->current_par->depth == 8)
-		bgx = attr_bgcol(p, sc);
-	else if (depth2bpp(l_fb_info->current_par->depth) == 16)
-		bgx = ((u16 *) p->dispsw_data)[attr_bgcol(p, sc)];
-	else
-		bgx = ((u32 *) p->dispsw_data)[attr_bgcol(p, sc)];
-	
-	PM3_COLOR(bgx);
-
-	PM3_WAIT(4);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0x3)) |	/* Ox3 is GXcopy */
-				  PM3Config2D_FBWriteEnable |
-				  PM3Config2D_OpaqueSpan);
-
-	PM3_WRITE_REG(PM3ForegroundColor, fgx);
-	PM3_WRITE_REG(PM3FillBackgroundColor, bgx);
-
-	/* WARNING : address select X need to specify 8 bits for fontwidth <= 8 */
-	/* and 16 bits for fontwidth <= 16 */
-	/* same in _putc, same for Y and fontheight */
-	if (fontwidth(p) <= 8)
-		asx = 2;
-	else if (fontwidth(p) <= 16)
-		asx = 3;	/* look OK */
-	if (fontheight(p) <= 8)
-		asy = 2;
-	else if (fontheight(p) <= 16)
-		asy = 3;	/* look OK */
-	else if (fontheight(p) <= 32)
-		asy = 4;	/* look OK */
-
-	sy = yy * fontheight(p);
-
-	if (fontheight(p) <= 8)
-		o_y = (8 - (sy & 0x7)) & 0x7;
-	else if (fontheight(p) <= 16)
-		o_y = (16 - (sy & 0xF)) & 0xF;
-	else if (fontheight(p) <= 32)
-		o_y = (32 - (sy & 0x1F)) & 0x1F;
-
-	for (j = 0; j < count; j++) {
-		sc = scr_readw(s + j);
-		if (fontwidth(p) <= 8)
-			cdat = p->fontdata +
-				(sc & p->charmask) * fontheight(p);
-		else
-			cdat = p->fontdata +
-				((sc & p->charmask) * fontheight(p) << 1);
-		
-		sx = (xx + j) * fontwidth(p);
-
-		if (fontwidth(p) <= 8)
-			o_x = (8 - (sx & 0x7)) & 0x7;
-		else if (fontwidth(p) <= 16)
-			o_x = (16 - (sx & 0xF)) & 0xF;
-
-		PM3_WAIT(3 + fontheight(p));
-
-		PM3_WRITE_REG(PM3AreaStippleMode, (o_x << 7) | (o_y << 12) | /* x_offset, y_offset in pattern */
-			      (1 << 18) | /* BE */
-			      1 | (asx << 1) | (asy << 4) | /* address select x/y */
-			      (1 << 20)); /* OpaqueSpan */
-
-		for (i = 0; i < fontheight(p); i++) { /* assume fontheight <= 32 */
-			if (fontwidth(p) <= 8) {
-				ldat = *cdat++;
-			} else { /* assume fontwidth <= 16 ATM */
-				ldat = ((*cdat++) << 8);
-				ldat |= *cdat++;
-			}
-			PM3_WRITE_REG(AreaStipplePattern_indexed(i), ldat);
-		}
-
-		PM3_WRITE_REG(PM3RectanglePosition,
-			      (PM3RectanglePosition_XOffset(sx)) |
-			      (PM3RectanglePosition_YOffset(sy)));
-
-		PM3_WRITE_REG(PM3Render2D,
-			      PM3Render2D_AreaStippleEnable |
-			      PM3Render2D_XPositive |
-			      PM3Render2D_YPositive |
-			      PM3Render2D_Operation_Normal |
-			      PM3Render2D_SpanOperation |
-			      (PM3Render2D_Width(fontwidth(p))) |
-			      (PM3Render2D_Height(fontheight(p))));
-	}
-	pm3fb_wait_pm3(l_fb_info);
-}
-
-static void pm3fb_cfbX_revc(struct display *p, int xx, int yy)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) p->fb_info;
-
-	xx = xx * fontwidth(p);
-	yy = yy * fontheight(p);
-
-	if (l_fb_info->current_par->depth == 8)
-	{
-		if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-			PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0x0F0F0F0F);
-		else
-			PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0x0F0F0F0F);
-	}
-
-	PM3_WAIT(3);
-
-	PM3_WRITE_REG(PM3Config2D,
-				  PM3Config2D_UseConstantSource |
-				  PM3Config2D_ForegroundROPEnable |
-				  (PM3Config2D_ForegroundROP(0xa)) |	/* Oxa is GXinvert */
-				  PM3Config2D_FBDestReadEnable |
-				  PM3Config2D_FBWriteEnable);
-
-	PM3_WRITE_REG(PM3RectanglePosition,
-		      (PM3RectanglePosition_XOffset(xx)) |
-		      (PM3RectanglePosition_YOffset(yy)));
-
-	PM3_WRITE_REG(PM3Render2D,
-		      PM3Render2D_XPositive |
-		      PM3Render2D_YPositive |
-		      PM3Render2D_Operation_Normal |
-		      PM3Render2D_SpanOperation |
-		      (PM3Render2D_Width(fontwidth(p))) |
-		      (PM3Render2D_Height(fontheight(p))));
-
-	pm3fb_wait_pm3(l_fb_info);
-
-	if (l_fb_info->current_par->depth == 8)
-	{
-		if (l_fb_info->memt.caps & PM3LocalMemCaps_NoWriteMask)
-			PM3_SLOW_WRITE_REG(PM3FBSoftwareWriteMask, 0xFFFFFFFF);
-		else
-			PM3_SLOW_WRITE_REG(PM3FBHardwareWriteMask, 0xFFFFFFFF);
-	}
-}
-
-#endif /* FBCON_HAS_CFB8 || FBCON_HAS_CFB16 || FBCON_HAS_CFB32 */
-#endif /* PM3FB_USE_ACCEL */
-/* *********************************** */
-/* ***** pre-init board(s) setup ***** */
-/* *********************************** */
-
-static void pm3fb_mode_setup(char *mode, unsigned long board_num)
-{
-	struct pm3fb_info *l_fb_info = &(fb_info[board_num]);
-	struct pm3fb_par *l_fb_par = &(current_par[board_num]);
-	unsigned long i = 0;
-
-	current_par_valid[board_num] = 0;
-
-	if (!strncmp(mode, "current", 7)) {
-		l_fb_info->use_current = 1;	/* default w/ OpenFirmware */
-	} else {
-		while ((mode_base[i].name[0])
-		       && (!current_par_valid[board_num])) {
-			if (!
-			    (strncmp
-			     (mode, mode_base[i].name,
-			      strlen(mode_base[i].name)))) {
-				memcpy(l_fb_par, &(mode_base[i].user_mode),
-				       sizeof(struct pm3fb_par));
-				current_par_valid[board_num] = 1;
-				DPRINTK(2, "Mode set to %s\n",
-					mode_base[i].name);
-			}
-			i++;
-		}
-		DASSERT(current_par_valid[board_num],
-			"Valid mode on command line\n");
-	}
-}
-
-static void pm3fb_pciid_setup(char *pciid, unsigned long board_num)
-{
-	short l_bus = -1, l_slot = -1, l_func = -1;
-	char *next;
-
-	if (pciid) {
-		l_bus = simple_strtoul(pciid, &next, 10);
-		if (next && (next[0] == ':')) {
-			pciid = next + 1;
-			l_slot = simple_strtoul(pciid, &next, 10);
-			if (next && (next[0] == ':')) {
-				pciid = next + 1;
-				l_func =
-				    simple_strtoul(pciid, (char **) NULL,
-						   10);
-			}
-		}
-	} else
-		return;
-
-	if ((l_bus >= 0) && (l_slot >= 0) && (l_func >= 0)) {
-		bus[board_num] = l_bus;
-		slot[board_num] = l_slot;
-		func[board_num] = l_func;
-		DPRINTK(2, "Board #%ld will be PciId: %hd:%hd:%hd\n",
-			board_num, l_bus, l_slot, l_func);
-	} else {
-		DPRINTK(1, "Invalid PciId: %hd:%hd:%hd for board #%ld\n",
-			l_bus, l_slot, l_func, board_num);
-	}
-}
-
-static void pm3fb_font_setup(char *lf, unsigned long board_num)
-{
-	unsigned long lfs = strlen(lf);
-
-	if (lfs > (PM3_FONTNAME_SIZE - 1)) {
-		DPRINTK(1, "Fontname %s too long\n", lf);
-		return;
-	}
-	strlcpy(fontn[board_num], lf, lfs + 1);
-}
-
-static void pm3fb_bootdepth_setup(char *bds, unsigned long board_num)
-{
-	unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
-
-	if (!(depth_supported(bd))) {
-		printk(KERN_WARNING "pm3fb: ignoring invalid depth %s for board #%ld\n",
-		       bds, board_num);
-		return;
-	}
-	depth[board_num] = bd;
-}
-
-static void pm3fb_forcesize_setup(char *bds, unsigned long board_num)
-{
-	unsigned long bd = simple_strtoul(bds, (char **) NULL, 10);
-
-	if (bd > 64) {
-		printk(KERN_WARNING "pm3fb: ignoring invalid memory size %s for board #%ld\n",
-		       bds, board_num);
-		return;
-	}
-	forcesize[board_num] = bd;
-}
-
-static char *pm3fb_boardnum_setup(char *options, unsigned long *bn)
-{
-	char *next;
-
-	if (!(isdigit(options[0]))) {
-		(*bn) = 0;
-		return (options);
-	}
-
-	(*bn) = simple_strtoul(options, &next, 10);
-
-	if (next && (next[0] == ':') && ((*bn) >= 0)
-	    && ((*bn) <= PM3_MAX_BOARD)) {
-		DPRINTK(2, "Board_num seen as %ld\n", (*bn));
-		return (next + 1);
-	} else {
-		(*bn) = 0;
-		DPRINTK(2, "Board_num default to %ld\n", (*bn));
-		return (options);
-	}
-}
-
-static void pm3fb_real_setup(char *options)
-{
-	char *next;
-	unsigned long i, bn;
-	struct pm3fb_info *l_fb_info;
-
-	DTRACE;
-
-	DPRINTK(2, "Options : %s\n", options);
-
-	for (i = 0; i < PM3_MAX_BOARD; i++) {
-		l_fb_info = &(fb_info[i]);
-		memset(l_fb_info, 0, sizeof(struct pm3fb_info));
-		l_fb_info->gen.fbhw = &pm3fb_switch;
-		l_fb_info->board_num = i;
-		current_par_valid[i] = 0;
-		slot[i] = -1;
-		func[i] = -1;
-		bus[i] = -1;
-		disable[i] = 0;
-		noaccel[i] = 0;
-		fontn[i][0] = '\0';
-		depth[i] = 0;
-		l_fb_info->current_par = &(current_par[i]);
-	}
-
-	/* eat up prefix pm3fb and whatever is used as separator i.e. :,= */
-	if (!strncmp(options, "pm3fb", 5)) {
-		options += 5;
-		while (((*options) == ',') || ((*options) == ':')
-		       || ((*options) == '='))
-			options++;
-	}
-
-	while (options) {
-		bn = 0;
-		if ((next = strchr(options, ','))) {
-			(*next) = '\0';
-			next++;
-		}
-
-		if (!strncmp(options, "mode:", 5)) {
-			options = pm3fb_boardnum_setup(options + 5, &bn);
-			DPRINTK(2, "Setting mode for board #%ld\n", bn);
-			pm3fb_mode_setup(options, bn);
-		} else if (!strncmp(options, "off:", 4)) {
-			options = pm3fb_boardnum_setup(options + 4, &bn);
-			DPRINTK(2, "Disabling board #%ld\n", bn);
-			disable[bn] = 1;
-		} else if (!strncmp(options, "off", 3)) {	/* disable everything */
-			for (i = 0; i < PM3_MAX_BOARD; i++)
-				disable[i] = 1;
-		} else if (!strncmp(options, "disable:", 8)) {
-			options = pm3fb_boardnum_setup(options + 8, &bn);
-			DPRINTK(2, "Disabling board #%ld\n", bn);
-			disable[bn] = 1;
-		} else if (!strncmp(options, "pciid:", 6)) {
-			options = pm3fb_boardnum_setup(options + 6, &bn);
-			DPRINTK(2, "Setting PciID for board #%ld\n", bn);
-			pm3fb_pciid_setup(options, bn);
-		} else if (!strncmp(options, "noaccel:", 8)) {
-			options = pm3fb_boardnum_setup(options + 8, &bn);
-			noaccel[bn] = 1;
-		} else if (!strncmp(options, "font:", 5)) {
-			options = pm3fb_boardnum_setup(options + 5, &bn);
-			pm3fb_font_setup(options, bn);
-		} else if (!strncmp(options, "depth:", 6)) {
-			options = pm3fb_boardnum_setup(options + 6, &bn);
-			pm3fb_bootdepth_setup(options, bn);
-		} else if (!strncmp(options, "printtimings", 12)) {
-			printtimings = 1;
-		} else if (!strncmp(options, "flatpanel:", 10)) {
-			options = pm3fb_boardnum_setup(options + 10, &bn);
-			flatpanel[bn] = 1;
-		} else if (!strncmp(options, "forcesize:", 10)) {
-			options = pm3fb_boardnum_setup(options + 10, &bn);
-			pm3fb_forcesize_setup(options, bn);
-		}
-		options = next;
-	}
-}
-
-/* ********************************************** */
-/* ***** framebuffer API standard functions ***** */
-/* ********************************************** */
-
-static int pm3fb_encode_fix(struct fb_fix_screeninfo *fix,
-			    const void *par, struct fb_info_gen *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-	struct pm3fb_par *p = (struct pm3fb_par *) par;
-
-	DTRACE;
-
-	strcpy(fix->id, permedia3_name);
-	fix->smem_start = (unsigned long)l_fb_info->p_fb;
-	fix->smem_len = l_fb_info->fb_size;
-	fix->mmio_start = (unsigned long)l_fb_info->pIOBase;
-	fix->mmio_len = PM3_REGS_SIZE;
-#ifdef PM3FB_USE_ACCEL
-	if (!(noaccel[l_fb_info->board_num]))
-		fix->accel = FB_ACCEL_3DLABS_PERMEDIA3;
-	else
-#endif /* PM3FB_USE_ACCEL */
-		fix->accel = FB_ACCEL_NONE;
-	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->visual =
-	    (p->depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
-	if (current_par_valid[l_fb_info->board_num])
-		fix->line_length =
-			l_fb_info->current_par->width *
-			depth2ByPP(l_fb_info->current_par->depth);
-	else
-		fix->line_length = 0;
-	fix->xpanstep = 64 / depth2bpp(p->depth);
-	fix->ypanstep = 1;
-	fix->ywrapstep = 0;
-	return (0);
-}
-
-static int pm3fb_decode_var(const struct fb_var_screeninfo *var,
-			    void *par, struct fb_info_gen *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-	struct pm3fb_par *p = (struct pm3fb_par *) par;
-	struct pm3fb_par temp_p;
-	u32 xres;
-
-	DTRACE;
-
-	DASSERT((var != NULL), "fb_var_screeninfo* not NULL");
-	DASSERT((p != NULL), "pm3fb_par* not NULL");
-	DASSERT((l_fb_info != NULL), "pm3fb_info* not NULL");
-
-	memset(&temp_p, 0, sizeof(struct pm3fb_par));
-	temp_p.width = (var->xres_virtual + 7) & ~7;
-	temp_p.height = var->yres_virtual;
-
-	if (!(depth_supported(var->bits_per_pixel))) /* round unsupported up to a multiple of 8 */
-		temp_p.depth = depth2bpp(var->bits_per_pixel);
-	else
-		temp_p.depth = var->bits_per_pixel;
-
-	temp_p.depth = (temp_p.depth > 32) ? 32 : temp_p.depth; /* max 32 */
-	temp_p.depth = (temp_p.depth == 24) ? 32 : temp_p.depth; /* 24 unsupported, round-up to 32 */
-
-	if ((temp_p.depth == 16) && (var->red.length == 5) && (var->green.length == 5) && (var->blue.length == 5))
-		temp_p.depth = 15; /* RGBA 5551 is stored as depth 15 */
-
-	if ((temp_p.depth == 16) && (var->red.length == 4) && (var->green.length == 4) && (var->blue.length == 4))
-		temp_p.depth = 12; /* RGBA 4444  is stored as depth 12 */
-
-
-	DPRINTK(2,
-		"xres: %d, yres: %d, vxres: %d, vyres: %d ; xoffset:%d, yoffset: %d\n",
-		var->xres, var->yres, var->xres_virtual, var->yres_virtual,
-		var->xoffset, var->yoffset);
-
-	xres = (var->xres + 31) & ~31;
-	if (temp_p.width < xres + var->xoffset)
-		temp_p.width = xres + var->xoffset;
-	if (temp_p.height < var->yres + var->yoffset)
-		temp_p.height = var->yres + var->yoffset;
-
-	if (temp_p.width > 2048) {
-		DPRINTK(1, "virtual width not supported: %u\n",
-			temp_p.width);
-		return (-EINVAL);
-	}
-	if (var->yres < 200) {
-		DPRINTK(1, "height not supported: %u\n", (u32) var->yres);
-		return (-EINVAL);
-	}
-	if (temp_p.height < 200 || temp_p.height > 4095) {
-		DPRINTK(1, "virtual height not supported: %u\n",
-			temp_p.height);
-		return (-EINVAL);
-	}
-	if (!(depth_supported(temp_p.depth))) {
-		DPRINTK(1, "depth not supported: %u\n", temp_p.depth);
-		return (-EINVAL);
-	}
-	if ((temp_p.width * temp_p.height * depth2ByPP(temp_p.depth)) >
-	    l_fb_info->fb_size) {
-		DPRINTK(1, "no memory for screen (%ux%ux%u)\n",
-			temp_p.width, temp_p.height, temp_p.depth);
-		return (-EINVAL);
-	}
-
-	if ((!var->pixclock) ||
-	    (!var->right_margin) ||
-	    (!var->hsync_len) ||
-	    (!var->left_margin) ||
-	    (!var->lower_margin) ||
-	    (!var->vsync_len) || (!var->upper_margin)
-	    ) {
-		unsigned long i = 0, done = 0;
-		printk(KERN_WARNING "pm3fb: refusing to use a likely wrong timing\n");
-
-		while ((mode_base[i].user_mode.width) && !done) {
-			if ((mode_base[i].user_mode.width == temp_p.width)
-			    && (mode_base[i].user_mode.height ==
-				temp_p.height)) {
-				printk(KERN_NOTICE "pm3fb: using close match %s\n",
-				       mode_base[i].name);
-				temp_p = mode_base[i].user_mode;
-				done = 1;
-			}
-			i++;
-		}
-		if (!done)
-			return (-EINVAL);
-	} else {
-		temp_p.pixclock = PICOS2KHZ(var->pixclock);
-		if (temp_p.pixclock > PM3_MAX_PIXCLOCK) {
-			DPRINTK(1, "pixclock too high (%uKHz)\n",
-				temp_p.pixclock);
-			return (-EINVAL);
-		}
-
-		temp_p.hsstart = var->right_margin;
-		temp_p.hsend = var->right_margin + var->hsync_len;
-		temp_p.hbend =
-		    var->right_margin + var->hsync_len + var->left_margin;
-		temp_p.htotal = xres + temp_p.hbend;
-
-		temp_p.vsstart = var->lower_margin;
-		temp_p.vsend = var->lower_margin + var->vsync_len;
-		temp_p.vbend =
-		    var->lower_margin + var->vsync_len + var->upper_margin;
-		temp_p.vtotal = var->yres + temp_p.vbend;
-
-		temp_p.stride = temp_p.width;
-
-		DPRINTK(2, "Using %d * %d, %d Khz, stride is %08x\n",
-			temp_p.width, temp_p.height, temp_p.pixclock,
-			temp_p.stride);
-
-		temp_p.base =
-		    pm3fb_Shiftbpp(l_fb_info, temp_p.depth,
-				   (var->yoffset * xres) + var->xoffset);
-
-		temp_p.video = 0;
-
-		if (var->sync & FB_SYNC_HOR_HIGH_ACT)
-			temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
-		else
-			temp_p.video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
-
-		if (var->sync & FB_SYNC_VERT_HIGH_ACT)
-			temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
-		else
-			temp_p.video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
-
-		if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
-			DPRINTK(1, "Interlaced mode not supported\n\n");
-			return (-EINVAL);
-		}
-
-		if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
-			temp_p.video |= PM3VideoControl_LINE_DOUBLE_ON;
-		else
-			temp_p.video |= PM3VideoControl_LINE_DOUBLE_OFF;
-
-		if (var->activate == FB_ACTIVATE_NOW)
-			temp_p.video |= PM3VideoControl_ENABLE;
-		else {
-			temp_p.video |= PM3VideoControl_DISABLE;
-			DPRINTK(2, "PM3Video disabled\n");
-		}
-
-		switch (temp_p.depth) {
-		case 8:
-			temp_p.video |= PM3VideoControl_PIXELSIZE_8BIT;
-			break;
-		case 12:
-		case 15:
-		case 16:
-			temp_p.video |= PM3VideoControl_PIXELSIZE_16BIT;
-			break;
-		case 32:
-			temp_p.video |= PM3VideoControl_PIXELSIZE_32BIT;
-			break;
-		default:
-			DPRINTK(1, "Unsupported depth\n");
-			break;
-		}
-	}
-	(*p) = temp_p;
-
-#ifdef PM3FB_USE_ACCEL
-	if (var->accel_flags & FB_ACCELF_TEXT)
-		noaccel[l_fb_info->board_num] = 0;
-	else
-		noaccel[l_fb_info->board_num] = 1;
-#endif /* PM3FB_USE_ACCEL */
-
-	return (0);
-}
-
-static void pm3fb_encode_depth(struct fb_var_screeninfo *var, long d)
-{
-	switch (d) {
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	switch(var->bits_per_pixel) {
 	case 8:
 		var->red.length = var->green.length = var->blue.length = 8;
 		var->red.offset = var->green.offset = var->blue.offset = 0;
-		var->transp.offset = var->transp.length = 0;
 		break;
-
 	case 12:
-		var->red.offset = 8;
-		var->red.length = 4;
+		var->red.offset   = 8;
+		var->red.length   = 4;
 		var->green.offset = 4;
 		var->green.length = 4;
-		var->blue.offset = 0;
-		var->blue.length = 4;
+		var->blue.offset  = 0;
+		var->blue.length  = 4;
 		var->transp.offset = 12;
 		var->transp.length = 4;
-		break;
-
 	case 15:
-		var->red.offset = 10;
-		var->red.length = 5;
+		var->red.offset   = 10;
+		var->red.length   = 5;
 		var->green.offset = 5;
 		var->green.length = 5;
-		var->blue.offset = 0;
-		var->blue.length = 5;
+		var->blue.offset  = 0;
+		var->blue.length  = 5;
 		var->transp.offset = 15;
 		var->transp.length = 1;
 		break;
-
 	case 16:
-		var->red.offset = 11;
-		var->red.length = 5;
+		var->red.offset   = 11;
+		var->red.length   = 5;
 		var->green.offset = 5;
 		var->green.length = 6;
-		var->blue.offset = 0;
-		var->blue.length = 5;
-		var->transp.offset = var->transp.length = 0;
+		var->blue.offset  = 0;
+		var->blue.length  = 5;
 		break;
-
 	case 32:
 		var->transp.offset = 24;
-		var->red.offset = 16;
+		var->transp.length = 8;
+		var->red.offset	  = 16;
 		var->green.offset = 8;
-		var->blue.offset = 0;
-		var->red.length = var->green.length =
-			var->blue.length = var->transp.length = 8;
+		var->blue.offset  = 0;
+		var->red.length = var->green.length = var->blue.length = 8;
 		break;
-
 	default:
-		DPRINTK(1, "Unsupported depth %ld\n", d);
-		break;
+		DPRINTK("depth not supported: %u\n", var->bits_per_pixel);
+		return -EINVAL;
 	}
-}
-
-static int pm3fb_encode_var(struct fb_var_screeninfo *var,
-			    const void *par, struct fb_info_gen *info)
-{
-	struct pm3fb_par *p = (struct pm3fb_par *) par;
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
-	u32 base;
-
-	DTRACE;
-
-	DASSERT((var != NULL), "fb_var_screeninfo* not NULL");
-	DASSERT((p != NULL), "pm3fb_par* not NULL");
-	DASSERT((info != NULL), "fb_info_gen* not NULL");
-
-	memset(var, 0, sizeof(struct fb_var_screeninfo));
-
-#ifdef PM3FB_USE_ACCEL
-	if (!(noaccel[l_fb_info->board_num]))
-		var->accel_flags |= FB_ACCELF_TEXT;
-#endif /* PM3FB_USE_ACCEL */
-
-	var->xres_virtual = p->width;
-	var->yres_virtual = p->height;
-	var->xres = p->htotal - p->hbend;
-	var->yres = p->vtotal - p->vbend;
-
-	DPRINTK(2, "xres = %d, yres : %d\n", var->xres, var->yres);
-
-	var->right_margin = p->hsstart;
-	var->hsync_len = p->hsend - p->hsstart;
-	var->left_margin = p->hbend - p->hsend;
-	var->lower_margin = p->vsstart;
-	var->vsync_len = p->vsend - p->vsstart;
-	var->upper_margin = p->vbend - p->vsend;
-	var->bits_per_pixel = depth2bpp(p->depth);
-	
-	pm3fb_encode_depth(var, p->depth);
-
-	base = pm3fb_Unshiftbpp(l_fb_info, p->depth, p->base);
-
-	var->xoffset = base % var->xres;
-	var->yoffset = base / var->xres;
-
 	var->height = var->width = -1;
 
-	var->pixclock = KHZ2PICOS(p->pixclock);
-
-	if ((p->video & PM3VideoControl_HSYNC_MASK) ==
-	    PM3VideoControl_HSYNC_ACTIVE_HIGH)
-		var->sync |= FB_SYNC_HOR_HIGH_ACT;
-	if ((p->video & PM3VideoControl_VSYNC_MASK) ==
-	    PM3VideoControl_VSYNC_ACTIVE_HIGH)
-		var->sync |= FB_SYNC_VERT_HIGH_ACT;
-	if (p->video & PM3VideoControl_LINE_DOUBLE_ON)
-		var->vmode = FB_VMODE_DOUBLE;
-
-	return (0);
-}
-
-static void pm3fb_get_par(void *par, struct fb_info_gen *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
-	DTRACE;
-
-	if (!current_par_valid[l_fb_info->board_num]) {
-		if (l_fb_info->use_current)
-			pm3fb_read_mode(l_fb_info, l_fb_info->current_par);
-		else
-			memcpy(l_fb_info->current_par,
-			       &(mode_base[0].user_mode),
-			       sizeof(struct pm3fb_par));
-		current_par_valid[l_fb_info->board_num] = 1;
+	if (var->xres != var->xres_virtual) {
+		DPRINTK("virtual x resolution != physical x resolution not supported\n");
+		return -EINVAL;
 	}
-	*((struct pm3fb_par *) par) = *(l_fb_info->current_par);
-}
 
-static void pm3fb_set_par(const void *par, struct fb_info_gen *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
-	DTRACE;
-
-	*(l_fb_info->current_par) = *((struct pm3fb_par *) par);
-	current_par_valid[l_fb_info->board_num] = 1;
-
-	pm3fb_write_mode(l_fb_info);
-
-#ifdef PM3FB_USE_ACCEL
-	pm3fb_init_engine(l_fb_info);
-#endif /* PM3FB_USE_ACCEL */
-}
-
-static void pm3fb_set_color(struct pm3fb_info *l_fb_info,
-			    unsigned char regno, unsigned char r,
-			    unsigned char g, unsigned char b)
-{
-	DTRACE;
-
-	PM3_SLOW_WRITE_REG(PM3RD_PaletteWriteAddress, regno);
-	PM3_SLOW_WRITE_REG(PM3RD_PaletteData, r);
-	PM3_SLOW_WRITE_REG(PM3RD_PaletteData, g);
-	PM3_SLOW_WRITE_REG(PM3RD_PaletteData, b);
-}
-
-static int pm3fb_getcolreg(unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
-	DTRACE;
-
-	if (regno < 256) {
-		*red =
-		    l_fb_info->palette[regno].red << 8 | l_fb_info->
-		    palette[regno].red;
-		*green =
-		    l_fb_info->palette[regno].green << 8 | l_fb_info->
-		    palette[regno].green;
-		*blue =
-		    l_fb_info->palette[regno].blue << 8 | l_fb_info->
-		    palette[regno].blue;
-		*transp =
-		    l_fb_info->palette[regno].transp << 8 | l_fb_info->
-		    palette[regno].transp;
+	if (var->yres > var->yres_virtual) {
+		DPRINTK("virtual y resolution < physical y resolution not possible\n");
+		return -EINVAL;
 	}
-	return (regno > 255);
+
+	if (var->xoffset) {
+		DPRINTK("xoffset not supported\n");
+		return -EINVAL;
+	}
+
+	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
+		DPRINTK("interlace not supported\n");
+		return -EINVAL;
+	}
+
+	var->xres = (var->xres + 31) & ~31; /* could sometimes be 8 */
+	lpitch = var->xres * ((var->bits_per_pixel + 7)>>3);
+
+	if (var->xres < 200 || var->xres > 2048) {
+		DPRINTK("width not supported: %u\n", var->xres);
+		return -EINVAL;
+	}
+
+	if (var->yres < 200 || var->yres > 4095) {
+		DPRINTK("height not supported: %u\n", var->yres);
+		return -EINVAL;
+	}
+
+	if (lpitch * var->yres_virtual > info->fix.smem_len) {
+		DPRINTK("no memory for screen (%ux%ux%u)\n",
+			var->xres, var->yres_virtual, var->bits_per_pixel);
+		return -EINVAL;
+	}
+
+	if (PICOS2KHZ(var->pixclock) > PM3_MAX_PIXCLOCK) {
+		DPRINTK("pixclock too high (%ldKHz)\n", PICOS2KHZ(var->pixclock));
+		return -EINVAL;
+	}
+
+	var->accel_flags = 0;	/* Can't mmap if this is on */
+
+	DPRINTK("Checking graphics mode at %dx%d depth %d\n",
+		var->xres, var->yres, var->bits_per_pixel);
+	return 0;
+}
+
+static int pm3fb_set_par(struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	const u32 xres = (info->var.xres + 31) & ~31;
+	const int depth = (info->var.bits_per_pixel + 7) & ~7;
+
+	par->base = pm3fb_shift_bpp(info->var.bits_per_pixel,
+					(info->var.yoffset * xres)
+					+ info->var.xoffset);
+	par->video = 0;
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		par->video |= PM3VideoControl_HSYNC_ACTIVE_HIGH;
+	else
+		par->video |= PM3VideoControl_HSYNC_ACTIVE_LOW;
+
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		par->video |= PM3VideoControl_VSYNC_ACTIVE_HIGH;
+	else
+		par->video |= PM3VideoControl_VSYNC_ACTIVE_LOW;
+
+	if ((info->var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE)
+		par->video |= PM3VideoControl_LINE_DOUBLE_ON;
+	else
+		par->video |= PM3VideoControl_LINE_DOUBLE_OFF;
+
+	if (info->var.activate == FB_ACTIVATE_NOW)
+		par->video |= PM3VideoControl_ENABLE;
+	else {
+		par->video |= PM3VideoControl_DISABLE;
+		DPRINTK("PM3Video disabled\n");
+	}
+	switch (depth) {
+	case 8:
+		par->video |= PM3VideoControl_PIXELSIZE_8BIT;
+		break;
+	case 12:
+	case 15:
+	case 16:
+		par->video |= PM3VideoControl_PIXELSIZE_16BIT;
+		break;
+	case 32:
+		par->video |= PM3VideoControl_PIXELSIZE_32BIT;
+		break;
+	default:
+		DPRINTK("Unsupported depth\n");
+		break;
+	}
+
+	info->fix.visual =
+		(depth == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.line_length = ((info->var.xres_virtual + 7)  & ~7)
+					* depth / 8;
+
+/*	pm3fb_clear_memory(info, 0);*/
+	pm3fb_clear_colormap(par, 0, 0, 0);
+	PM3_WRITE_DAC_REG(par, PM3RD_CursorMode,
+			  PM3RD_CursorMode_CURSOR_DISABLE);
+	pm3fb_write_mode(info);
+	return 0;
 }
 
 static int pm3fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 			   unsigned blue, unsigned transp,
 			   struct fb_info *info)
 {
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
+	struct pm3_par *par = info->par;
 
-	DTRACE;
+	if (regno >= 256)  /* no. of hw registers */
+	   return -EINVAL;
 
-	if (regno < 16) {
-		switch (l_fb_info->current_par->depth) {
-#ifdef FBCON_HAS_CFB8
+	/* grayscale works only partially under directcolor */
+	if (info->var.grayscale) {
+	   /* grayscale = 0.30*R + 0.59*G + 0.11*B */
+	   red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Directcolor:
+	 *   var->{color}.offset contains start of bitfield
+	 *   var->{color}.length contains length of bitfield
+	 *   {hardwarespecific} contains width of DAC
+	 *   pseudo_palette[X] is programmed to (X << red.offset) |
+	 *				      (X << green.offset) |
+	 *				      (X << blue.offset)
+	 *   RAMDAC[X] is programmed to (red, green, blue)
+	 *   color depth = SUM(var->{color}.length)
+	 *
+	 * Pseudocolor:
+	 *	var->{color}.offset is 0
+	 *	var->{color}.length contains width of DAC or the number of unique
+	 *			colors available (color depth)
+	 *	pseudo_palette is not used
+	 *	RAMDAC[X] is programmed to (red, green, blue)
+	 *	color depth = var->{color}.length
+	 */
+
+	/*
+	 * This is the point where the color is converted to something that
+	 * is acceptable by the hardware.
+	 */
+#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+	red = CNVT_TOHW(red, info->var.red.length);
+	green = CNVT_TOHW(green, info->var.green.length);
+	blue = CNVT_TOHW(blue, info->var.blue.length);
+	transp = CNVT_TOHW(transp, info->var.transp.length);
+#undef CNVT_TOHW
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+	info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v = (red << info->var.red.offset) |
+			(green << info->var.green.offset) |
+			(blue << info->var.blue.offset) |
+			(transp << info->var.transp.offset);
+
+		switch (info->var.bits_per_pixel) {
 		case 8:
 			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 12:
-			l_fb_info->cmap.cmap12[regno] =
-				(((u32) red & 0xf000) >> 4) |
-				(((u32) green & 0xf000) >> 8) |
-				(((u32) blue & 0xf000) >> 12);
-			break;
-
-		case 15:
-			l_fb_info->cmap.cmap15[regno] =
-				(((u32) red & 0xf800) >> 1) |
-				(((u32) green & 0xf800) >> 6) |
-				(((u32) blue & 0xf800) >> 11);
-			break;
-
 		case 16:
-			l_fb_info->cmap.cmap16[regno] =
-			    ((u32) red & 0xf800) |
-			    (((u32) green & 0xfc00) >> 5) |
-			    (((u32) blue & 0xf800) >> 11);
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
+		case 24:
 		case 32:
-			l_fb_info->cmap.cmap32[regno] =
-			    (((u32) transp & 0xff00) << 16) |
-			    (((u32) red & 0xff00) << 8) |
-			    (((u32) green & 0xff00)) |
-			    (((u32) blue & 0xff00) >> 8);
-			break;
-#endif
-		default:
-			DPRINTK(1, "bad depth %u\n",
-				l_fb_info->current_par->depth);
+			((u32*)(info->pseudo_palette))[regno] = v;
 			break;
 		}
+		return 0;
 	}
-	if (regno < 256) {
-		l_fb_info->palette[regno].red = red >> 8;
-		l_fb_info->palette[regno].green = green >> 8;
-		l_fb_info->palette[regno].blue = blue >> 8;
-		l_fb_info->palette[regno].transp = transp >> 8;
-		if (l_fb_info->current_par->depth == 8)
-			pm3fb_set_color(l_fb_info, regno, red >> 8,
-					green >> 8, blue >> 8);
-	}
-	return (regno > 255);
+	else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR)
+		pm3fb_set_color(par, regno, red, green, blue);
+
+	return 0;
 }
 
-static int pm3fb_blank(int blank_mode, struct fb_info_gen *info)
+static int pm3fb_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
 {
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-	u32 video;
+	struct pm3_par *par = info->par;
+	const u32 xres = (var->xres + 31) & ~31;
 
-	DTRACE;
+	par->base = pm3fb_shift_bpp(var->bits_per_pixel,
+					(var->yoffset * xres)
+					+ var->xoffset);
+	PM3_SLOW_WRITE_REG(par, PM3ScreenBase, par->base);
+	return 0;
+}
 
-	if (!current_par_valid[l_fb_info->board_num])
-		return (1);
-
-	video = l_fb_info->current_par->video;
+static int pm3fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct pm3_par *par = info->par;
+	u32 video = par->video;
 
 	/*
 	 * Oxygen VX1 - it appears that setting PM3VideoControl and
@@ -3181,454 +663,345 @@
 	video |= PM3VideoControl_HSYNC_ACTIVE_HIGH |
 		 PM3VideoControl_VSYNC_ACTIVE_HIGH;
 
-	if (blank_mode > 0) {
-		switch (blank_mode - 1) {
-
-		case VESA_NO_BLANKING:	/* FIXME */
-			video = video & ~(PM3VideoControl_ENABLE);
-			break;
-
-		case VESA_HSYNC_SUSPEND:
-			video = video & ~(PM3VideoControl_HSYNC_MASK |
-					  PM3VideoControl_BLANK_ACTIVE_LOW);
-			break;
-		case VESA_VSYNC_SUSPEND:
-			video = video & ~(PM3VideoControl_VSYNC_MASK |
-					  PM3VideoControl_BLANK_ACTIVE_LOW);
-			break;
-		case VESA_POWERDOWN:
-			video = video & ~(PM3VideoControl_HSYNC_MASK |
-					  PM3VideoControl_VSYNC_MASK |
-					  PM3VideoControl_BLANK_ACTIVE_LOW);
-			break;
-		default:
-			DPRINTK(1, "Unsupported blanking %d\n",
-				blank_mode);
-			return (1);
-			break;
-		}
-	}
-
-	PM3_SLOW_WRITE_REG(PM3VideoControl, video);
-
-	return (0);
-}
-
-static void pm3fb_set_disp(const void *par, struct display *disp,
-			   struct fb_info_gen *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-	struct pm3fb_par *p = (struct pm3fb_par *) par;
-	u32 flags;
-
-	DTRACE;
-
-	local_irq_save(flags);
-	info->info.screen_base = l_fb_info->v_fb;
-	switch (p->depth) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-#ifdef PM3FB_USE_ACCEL
-		if (!(noaccel[l_fb_info->board_num]))
-			disp->dispsw = &pm3fb_cfb8;
-		else
-#endif /* PM3FB_USE_ACCEL */
-			disp->dispsw = &fbcon_cfb8;
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		video = video | PM3VideoControl_ENABLE;
 		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 12:
-#ifdef PM3FB_USE_ACCEL
-		if (!(noaccel[l_fb_info->board_num]))
-			disp->dispsw = &pm3fb_cfb16;
-		else
-#endif /* PM3FB_USE_ACCEL */
-			disp->dispsw = &fbcon_cfb16;
-		disp->dispsw_data = l_fb_info->cmap.cmap12;
+	case FB_BLANK_NORMAL:	/* FIXME */
+		video = video & ~(PM3VideoControl_ENABLE);
 		break;
-	case 15:
-#ifdef PM3FB_USE_ACCEL
-		if (!(noaccel[l_fb_info->board_num]))
-			disp->dispsw = &pm3fb_cfb16;
-		else
-#endif /* PM3FB_USE_ACCEL */
-			disp->dispsw = &fbcon_cfb16;
-		disp->dispsw_data = l_fb_info->cmap.cmap15;
+	case FB_BLANK_HSYNC_SUSPEND:
+		video = video & ~(PM3VideoControl_HSYNC_MASK |
+				  PM3VideoControl_BLANK_ACTIVE_LOW);
 		break;
-	case 16:
-#ifdef PM3FB_USE_ACCEL
-		if (!(noaccel[l_fb_info->board_num]))
-			disp->dispsw = &pm3fb_cfb16;
-		else
-#endif /* PM3FB_USE_ACCEL */
-			disp->dispsw = &fbcon_cfb16;
-		disp->dispsw_data = l_fb_info->cmap.cmap16;
+	case FB_BLANK_VSYNC_SUSPEND:
+		video = video & ~(PM3VideoControl_VSYNC_MASK |
+				  PM3VideoControl_BLANK_ACTIVE_LOW);
 		break;
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 32:
-#ifdef PM3FB_USE_ACCEL
-		if (!(noaccel[l_fb_info->board_num]))
-			disp->dispsw = &pm3fb_cfb32;
-		else
-#endif /* PM3FB_USE_ACCEL */
-			disp->dispsw = &fbcon_cfb32;
-		disp->dispsw_data = l_fb_info->cmap.cmap32;
+	case FB_BLANK_POWERDOWN:
+		video = video & ~(PM3VideoControl_HSYNC_MASK |
+				  PM3VideoControl_VSYNC_MASK |
+				  PM3VideoControl_BLANK_ACTIVE_LOW);
 		break;
-#endif /* FBCON_HAS_CFB32 */
 	default:
-		disp->dispsw = &fbcon_dummy;
-		DPRINTK(1, "Invalid depth, using fbcon_dummy\n");
-		break;
-	}
-	local_irq_restore(flags);
-}
-
-/* */
-static void pm3fb_detect(void)
-{
-	struct pci_dev *dev_array[PM3_MAX_BOARD];
-	struct pci_dev *dev = NULL;
-	struct pm3fb_info *l_fb_info = &(fb_info[0]);
-	unsigned long i, j, done;
-
-	DTRACE;
-
-	for (i = 0; i < PM3_MAX_BOARD; i++) {
-		dev_array[i] = NULL;
-		fb_info[i].dev = NULL;
+		DPRINTK("Unsupported blanking %d\n", blank_mode);
+		return 1;
 	}
 
-	dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
-			    PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
+	PM3_SLOW_WRITE_REG(par,PM3VideoControl, video);
 
-	for (i = 0; ((i < PM3_MAX_BOARD) && dev); i++) {
-		dev_array[i] = dev;
-		dev = pci_get_device(PCI_VENDOR_ID_3DLABS,
-				    PCI_DEVICE_ID_3DLABS_PERMEDIA3, dev);
-	}
-
-	if (dev) {		/* more than PM3_MAX_BOARD */
-		printk(KERN_WARNING "pm3fb: Warning: more than %d boards found\n",
-		       PM3_MAX_BOARD);
-	}
-
-	if (!dev_array[0]) {	/* not a single board, abort */
-		return;
-	}
-
-	/* allocate user-defined boards */
-	for (i = 0; i < PM3_MAX_BOARD; i++) {
-		if ((bus[i] >= 0) && (slot[i] >= 0) && (func[i] >= 0)) {
-			for (j = 0; j < PM3_MAX_BOARD; j++) {
-				if ((dev_array[j] != NULL) &&
-				    (dev_array[j]->bus->number == bus[i])
-				    && (PCI_SLOT(dev_array[j]->devfn) ==
-					slot[i])
-				    && (PCI_FUNC(dev_array[j]->devfn) ==
-					func[i])) {
-					fb_info[i].dev = dev_array[j];
-					dev_array[j] = NULL;
-				}
-			}
-		}
-	}
-	/* allocate remaining boards */
-	for (i = 0; i < PM3_MAX_BOARD; i++) {
-		if (fb_info[i].dev == NULL) {
-			done = 0;
-			for (j = 0; ((j < PM3_MAX_BOARD) && (!done)); j++) {
-				if (dev_array[j] != NULL) {
-					fb_info[i].dev = dev_array[j];
-					dev_array[j] = NULL;
-					done = 1;
-				}
-			}
-		}
-	}
-
-	/* at that point, all PCI Permedia3 are detected and allocated */
-	/* now, initialize... or not */
-	for (i = 0; i < PM3_MAX_BOARD; i++) {
-		l_fb_info = &(fb_info[i]);
-		if (l_fb_info->dev && !disable[i]) {	/* PCI device was found and not disabled by user */
-			DPRINTK(2,
-				"found @%lx Vendor %lx Device %lx ; base @ : %lx - %lx - %lx - %lx - %lx - %lx, irq %ld\n",
-				(unsigned long) l_fb_info->dev,
-				(unsigned long) l_fb_info->dev->vendor,
-				(unsigned long) l_fb_info->dev->device,
-				(unsigned long)
-				pci_resource_start(l_fb_info->dev, 0),
-				(unsigned long)
-				pci_resource_start(l_fb_info->dev, 1),
-				(unsigned long)
-				pci_resource_start(l_fb_info->dev, 2),
-				(unsigned long)
-				pci_resource_start(l_fb_info->dev, 3),
-				(unsigned long)
-				pci_resource_start(l_fb_info->dev, 4),
-				(unsigned long)
-				pci_resource_start(l_fb_info->dev, 5),
-				(unsigned long) l_fb_info->dev->irq);
-
-			l_fb_info->pIOBase =
-			    (unsigned char *)
-			    pci_resource_start(l_fb_info->dev, 0);
-#ifdef __BIG_ENDIAN
-			l_fb_info->pIOBase += PM3_REGS_SIZE;
-#endif
-			l_fb_info->vIOBase = (unsigned char *) -1;
-			l_fb_info->p_fb =
-			    (unsigned char *)
-			    pci_resource_start(l_fb_info->dev, 1);
-			l_fb_info->v_fb = (unsigned char *) -1;
-
-				if (!request_mem_region
-			    ((unsigned long)l_fb_info->p_fb, 64 * 1024 * 1024, /* request full aperture size */
-			     "pm3fb")) {
-				printk
-				    (KERN_ERR "pm3fb: Error: couldn't request framebuffer memory, board #%ld\n",
-				     l_fb_info->board_num);
-				continue;
-			}
-			if (!request_mem_region
-			    ((unsigned long)l_fb_info->pIOBase, PM3_REGS_SIZE,
-			     "pm3fb I/O regs")) {
-				printk
-				    (KERN_ERR "pm3fb: Error: couldn't request IObase memory, board #%ld\n",
-				     l_fb_info->board_num);
-				continue;
-			}
-			if (forcesize[l_fb_info->board_num])
-				l_fb_info->fb_size = forcesize[l_fb_info->board_num];
-
-			l_fb_info->fb_size =
-			    pm3fb_size_memory(l_fb_info);
-				if (l_fb_info->fb_size) {
-				(void) pci_enable_device(l_fb_info->dev);
-				pm3fb_common_init(l_fb_info);
-			} else
-				printk(KERN_ERR "pm3fb: memory problem, not enabling board #%ld\n", l_fb_info->board_num);
-		}
-	}
-}
-
-static int pm3fb_pan_display(const struct fb_var_screeninfo *var,
-			     struct fb_info_gen *info)
-{
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-
-	DTRACE;
-
-	if (!current_par_valid[l_fb_info->board_num])
-		return -EINVAL;
-
-	l_fb_info->current_par->base =	/* in 128 bits chunk - i.e. AFTER Shiftbpp */
-	    pm3fb_Shiftbpp(l_fb_info,
-			   l_fb_info->current_par->depth,
-			   (var->yoffset * l_fb_info->current_par->width) +
-			   var->xoffset);
-	PM3_SLOW_WRITE_REG(PM3ScreenBase, l_fb_info->current_par->base);
 	return 0;
 }
 
-static int pm3fb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
+	/*
+	 *  Frame buffer operations
+	 */
+
+static struct fb_ops pm3fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= pm3fb_check_var,
+	.fb_set_par	= pm3fb_set_par,
+	.fb_setcolreg	= pm3fb_setcolreg,
+	.fb_pan_display	= pm3fb_pan_display,
+	.fb_fillrect	= cfb_fillrect,		/* Needed !!! */
+	.fb_copyarea	= cfb_copyarea,		/* Needed !!! */
+	.fb_imageblit	= cfb_imageblit,	/* Needed !!! */
+	.fb_blank	= pm3fb_blank,
+};
+
+/* ------------------------------------------------------------------------- */
+
+	/*
+	 *  Initialization
+	 */
+
+/* mmio register are already mapped when this function is called */
+/* the pm3fb_fix.smem_start is also set */
+static unsigned long pm3fb_size_memory(struct pm3_par *par)
 {
-	struct pm3fb_info *l_fb_info = (struct pm3fb_info *) info;
-	u32 cm, i;
-#ifdef PM3FB_MASTER_DEBUG
-	char cc[3];
-#endif /* PM3FB_MASTER_DEBUG */
+	unsigned long	memsize = 0, tempBypass, i, temp1, temp2;
+	unsigned char	__iomem *screen_mem;
 
-	switch(cmd)
+	pm3fb_fix.smem_len = 64 * 1024 * 1024; /* request full aperture size */
+	/* Linear frame buffer - request region and map it. */
+	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
+				 "pm3fb smem")) {
+		printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
+		return 0;
+	}
+	screen_mem =
+		ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+	if (!screen_mem) {
+		printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
+		release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+		return 0;
+	}
+
+	/* TODO: card-specific stuff, *before* accessing *any* FB memory */
+	/* For Appian Jeronimo 2000 board second head */
+
+	tempBypass = PM3_READ_REG(par, PM3MemBypassWriteMask);
+
+	DPRINTK("PM3MemBypassWriteMask was: 0x%08lx\n", tempBypass);
+
+	PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, 0xFFFFFFFF);
+
+	/* pm3 split up memory, replicates, and do a lot of nasty stuff IMHO ;-) */
+	for (i = 0; i < 32; i++) {
+		fb_writel(i * 0x00345678,
+			  (screen_mem + (i * 1048576)));
+		mb();
+		temp1 = fb_readl((screen_mem + (i * 1048576)));
+
+		/* Let's check for wrapover, write will fail at 16MB boundary */
+		if (temp1 == (i * 0x00345678))
+			memsize = i;
+		else
+			break;
+	}
+
+	DPRINTK("First detect pass already got %ld MB\n", memsize + 1);
+
+	if (memsize + 1 == i) {
+		for (i = 0; i < 32; i++) {
+			/* Clear first 32MB ; 0 is 0, no need to byteswap */
+			writel(0x0000000,
+			       (screen_mem + (i * 1048576)));
+			mb();
+		}
+
+		for (i = 32; i < 64; i++) {
+			fb_writel(i * 0x00345678,
+				  (screen_mem + (i * 1048576)));
+			mb();
+			temp1 =
+			    fb_readl((screen_mem + (i * 1048576)));
+			temp2 =
+			    fb_readl((screen_mem + ((i - 32) * 1048576)));
+			/* different value, different RAM... */
+			if ((temp1 == (i * 0x00345678)) && (temp2 == 0))
+				memsize = i;
+			else
+				break;
+		}
+	}
+	DPRINTK("Second detect pass got %ld MB\n", memsize + 1);
+
+	PM3_SLOW_WRITE_REG(par, PM3MemBypassWriteMask, tempBypass);
+
+	iounmap(screen_mem);
+	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+	memsize = 1048576 * (memsize + 1);
+
+	DPRINTK("Returning 0x%08lx bytes\n", memsize);
+
+	return memsize;
+}
+
+static int __devinit pm3fb_probe(struct pci_dev *dev,
+				  const struct pci_device_id *ent)
+{
+	struct fb_info *info;
+	struct pm3_par *par;
+	struct device* device = &dev->dev; /* for pci drivers */
+	int err, retval = -ENXIO;
+
+	err = pci_enable_device(dev);
+	if (err) {
+		printk(KERN_WARNING "pm3fb: Can't enable PCI dev: %d\n", err);
+		return err;
+	}
+	/*
+	 * Dynamically allocate info and par
+	 */
+	info = framebuffer_alloc(sizeof(struct pm3_par), device);
+
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+
+	/*
+	 * Here we set the screen_base to the virtual memory address
+	 * for the framebuffer.
+	 */
+	pm3fb_fix.mmio_start = pci_resource_start(dev, 0);
+	pm3fb_fix.mmio_len = PM3_REGS_SIZE;
+
+	/* Registers - request region and map it. */
+	if (!request_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len,
+				 "pm3fb regbase")) {
+		printk(KERN_WARNING "pm3fb: Can't reserve regbase.\n");
+		goto err_exit_neither;
+	}
+	par->v_regs =
+		ioremap_nocache(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+	if (!par->v_regs) {
+		printk(KERN_WARNING "pm3fb: Can't remap %s register area.\n",
+			pm3fb_fix.id);
+		release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+		goto err_exit_neither;
+	}
+
+#if defined(__BIG_ENDIAN)
+	pm3fb_fix.mmio_start += PM3_REGS_SIZE;
+	DPRINTK("Adjusting register base for big-endian.\n");
+#endif
+	/* Linear frame buffer - request region and map it. */
+	pm3fb_fix.smem_start = pci_resource_start(dev, 1);
+	pm3fb_fix.smem_len = pm3fb_size_memory(par);
+	if (!pm3fb_fix.smem_len)
 	{
-#ifdef PM3FB_MASTER_DEBUG
-	case PM3FBIO_CLEARMEMORY:
-		if (copy_from_user(&cm, (void *)arg, sizeof(u32)))
-			return(-EFAULT);
-		pm3fb_clear_memory(l_fb_info, cm);
-		return(0);
-		break;
+		printk(KERN_WARNING "pm3fb: Can't find memory on board.\n");
+		goto err_exit_mmio;
+	}
+	if (!request_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len,
+				 "pm3fb smem")) {
+		printk(KERN_WARNING "pm3fb: Can't reserve smem.\n");
+		goto err_exit_mmio;
+	}
+	info->screen_base =
+		ioremap_nocache(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_WARNING "pm3fb: Can't ioremap smem area.\n");
+		release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+		goto err_exit_mmio;
+	}
+	info->screen_size = pm3fb_fix.smem_len;
 
-	case PM3FBIO_CLEARCMAP:
-		if (copy_from_user(cc, (void*)arg, 3 * sizeof(char)))
-			return(-EFAULT);
-		pm3fb_clear_colormap(l_fb_info, cc[0], cc[1], cc[2]);
-		return(0);
-		break;
-#endif /* PM3FB_MASTER_DEBUG */
+	info->fbops = &pm3fb_ops;
 
-	case PM3FBIO_RESETCHIP:
-		cm = 1;
-		PM3_SLOW_WRITE_REG(PM3ResetStatus, 1);
-		for (i = 0 ; (i < 10000) && cm ; i++)
-		{
-			PM3_DELAY(10);
-			cm = PM3_READ_REG(PM3ResetStatus);
-		}
-		if (cm)
-		{
-			printk(KERN_ERR "pm3fb: chip reset failed with status 0x%x\n", cm);
-			return(-EIO);
-		}
-		/* first thing first, reload memory timings */
-		pm3fb_write_memory_timings(l_fb_info);
-#ifdef PM3FB_USE_ACCEL
-		pm3fb_init_engine(l_fb_info);
-#endif /* PM3FB_USE_ACCEL */
-		pm3fb_write_mode(l_fb_info);
-		return(0);
-		break;
+	par->video = PM3_READ_REG(par, PM3VideoControl);
 
-	default:
-		DPRINTK(2, "unknown ioctl: %d (%x)\n", cmd, cmd);
-		return(-EINVAL);
+	info->fix = pm3fb_fix;
+	info->pseudo_palette = par->palette;
+	info->flags = FBINFO_DEFAULT;/* | FBINFO_HWACCEL_YPAN;*/
+
+	/*
+	 * This should give a reasonable default video mode. The following is
+	 * done when we can set a video mode.
+	 */
+	if (!mode_option)
+		mode_option = "640x480@60";
+
+	retval = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8);
+
+	if (!retval || retval == 4) {
+		retval = -EINVAL;
+		goto err_exit_both;
+	}
+
+	/* This has to been done !!! */
+	if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) {
+		retval = -ENOMEM;
+		goto err_exit_both;
+	}
+
+	/*
+	 * For drivers that can...
+	 */
+	pm3fb_check_var(&info->var, info);
+
+	if (register_framebuffer(info) < 0) {
+		retval = -EINVAL;
+		goto err_exit_all;
+	}
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
+	   info->fix.id);
+	pci_set_drvdata(dev, info); /* or dev_set_drvdata(device, info) */
+	return 0;
+
+ err_exit_all:
+	fb_dealloc_cmap(&info->cmap);
+ err_exit_both:
+	iounmap(info->screen_base);
+	release_mem_region(pm3fb_fix.smem_start, pm3fb_fix.smem_len);
+ err_exit_mmio:
+	iounmap(par->v_regs);
+	release_mem_region(pm3fb_fix.mmio_start, pm3fb_fix.mmio_len);
+ err_exit_neither:
+	framebuffer_release(info);
+	return retval;
+}
+
+	/*
+	 *  Cleanup
+	 */
+static void __devexit pm3fb_remove(struct pci_dev *dev)
+{
+	struct fb_info *info = pci_get_drvdata(dev);
+
+	if (info) {
+		struct fb_fix_screeninfo *fix = &info->fix;
+		struct pm3_par *par = info->par;
+
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+
+		iounmap(info->screen_base);
+		release_mem_region(fix->smem_start, fix->smem_len);
+		iounmap(par->v_regs);
+		release_mem_region(fix->mmio_start, fix->mmio_len);
+
+		pci_set_drvdata(dev, NULL);
+		framebuffer_release(info);
 	}
 }
 
-/* ****************************************** */
-/* ***** standard FB API init functions ***** */
-/* ****************************************** */
+static struct pci_device_id pm3fb_id_table[] = {
+	{ PCI_VENDOR_ID_3DLABS, 0x0a,
+	  PCI_ANY_ID, PCI_ANY_ID, PCI_BASE_CLASS_DISPLAY << 16,
+	  0xff0000, 0 },
+	{ 0, }
+};
 
-int __init pm3fb_setup(char *options)
-{
-	long opsi = strlen(options);
+/* For PCI drivers */
+static struct pci_driver pm3fb_driver = {
+	.name =		"pm3fb",
+	.id_table =	pm3fb_id_table,
+	.probe =	pm3fb_probe,
+	.remove =	__devexit_p(pm3fb_remove),
+};
 
-	DTRACE;
-
-	memcpy(g_options, options,
-	       ((opsi + 1) >
-		PM3_OPTIONS_SIZE) ? PM3_OPTIONS_SIZE : (opsi + 1));
-	g_options[PM3_OPTIONS_SIZE - 1] = 0;
-
-	return (0);
-}
+MODULE_DEVICE_TABLE(pci, pm3fb_id_table);
 
 int __init pm3fb_init(void)
 {
-	DTRACE;
+	/*
+	 *  For kernel boot options (in 'video=pm3fb:<options>' format)
+	 */
+#ifndef MODULE
+	char *option = NULL;
 
-	DPRINTK(2, "This is pm3fb.c, CVS version: $Header: /cvsroot/linux/drivers/video/pm3fb.c,v 1.1 2002/02/25 19:11:06 marcelo Exp $");
+	if (fb_get_options("pm3fb", &option))
+		return -ENODEV;
+	pm3fb_setup(option);
+#endif
 
-	pm3fb_real_setup(g_options);
-
-	pm3fb_detect();
-
-	if (!fb_info[0].dev) {	/* not even one board ??? */
-		DPRINTK(1, "No PCI Permedia3 board detected\n");
-	}
-	return (0);
+	return pci_register_driver(&pm3fb_driver);
 }
 
-/* ************************* */
-/* **** Module support ***** */
-/* ************************* */
+static void __exit pm3fb_exit(void)
+{
+	pci_unregister_driver(&pm3fb_driver);
+}
 
 #ifdef MODULE
-MODULE_AUTHOR("Romain Dolbeau");
-MODULE_DESCRIPTION("Permedia3 framebuffer device driver");
-static char *mode[PM3_MAX_BOARD];
-module_param_array(mode, charp, NULL, 0);
-MODULE_PARM_DESC(mode,"video mode");
-module_param_array(disable, short, NULL, 0);
-MODULE_PARM_DESC(disable,"disable board");
-static short off[PM3_MAX_BOARD];
-module_param_array(off, short, NULL, 0);
-MODULE_PARM_DESC(off,"disable board");
-static char *pciid[PM3_MAX_BOARD];
-module_param_array(pciid, charp, NULL, 0);
-MODULE_PARM_DESC(pciid,"board PCI Id");
-module_param_array(noaccel, short, NULL, 0);
-MODULE_PARM_DESC(noaccel,"disable accel");
-static char *font[PM3_MAX_BOARD];
-module_param_array(font, charp, NULL, 0);
-MODULE_PARM_DESC(font,"choose font");
-module_param(depth, short, NULL, 0);
-MODULE_PARM_DESC(depth,"boot-time depth");
-module_param(printtimings, short, NULL, 0);
-MODULE_PARM_DESC(printtimings, "print the memory timings of the card(s)");
-module_param(forcesize, short, NULL, 0);
-MODULE_PARM_DESC(forcesize, "force specified memory size");
+	/*
+	 *  Setup
+	 */
+
 /*
-MODULE_SUPPORTED_DEVICE("Permedia3 PCI boards")
-MODULE_GENERIC_TABLE(gtype,name)
-MODULE_DEVICE_TABLE(type,name)
-*/
-
-void pm3fb_build_options(void)
+ * Only necessary if your driver takes special options,
+ * otherwise we fall back on the generic fb_setup().
+ */
+int __init pm3fb_setup(char *options)
 {
-	int i;
-	char ts[128];
-
-	strcpy(g_options, "pm3fb");
-	for (i = 0; i < PM3_MAX_BOARD ; i++)
-	{
-		if (mode[i])
-		{
-			sprintf(ts, ",mode:%d:%s", i, mode[i]);
-			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-		}
-		if (disable[i] || off[i])
-		{
-			sprintf(ts, ",disable:%d:", i);
-			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-		}
-		if (pciid[i])
-		{
-			sprintf(ts, ",pciid:%d:%s", i, pciid[i]);
-			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-		}
-		if (noaccel[i])
-		{
-			sprintf(ts, ",noaccel:%d:", i);
-			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-		}
-		if (font[i])
-		{
-			sprintf(ts, ",font:%d:%s", i, font[i]);
-			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-		}
-		if (depth[i])
-		{
-			sprintf(ts, ",depth:%d:%d", i, depth[i]);
-			strncat(g_options, ts, PM3_OPTIONS_SIZE - strlen(g_options));
-		}
-	}
-	g_options[PM3_OPTIONS_SIZE - 1] = '\0';
-	DPRINTK(1, "pm3fb use options: %s\n", g_options);
-}
-
-int init_module(void)
-{
-	DTRACE;
-
-	pm3fb_build_options();
-
-	pm3fb_init();
-
+	/* Parse user speficied options (`video=pm3fb:') */
 	return 0;
 }
-
-void cleanup_module(void)
-{
-	DTRACE;
-	{
-		unsigned long i;
-		struct pm3fb_info *l_fb_info;
-		for (i = 0; i < PM3_MAX_BOARD; i++) {
-			l_fb_info = &(fb_info[i]);
-			pci_dev_put(l_fb_info->dev);
-			if (l_fb_info->dev != NULL  && !(disable[l_fb_info->board_num])) {
-				if (l_fb_info->vIOBase != (unsigned char *) -1) {
-					pm3fb_unmapIO(l_fb_info);
-					release_mem_region(l_fb_info->p_fb,
-						   l_fb_info->fb_size);
-					release_mem_region(l_fb_info->pIOBase,
-						   PM3_REGS_SIZE);
-				}
-				unregister_framebuffer(&l_fb_info->gen.info);
-			}
-		}
-	}
-}
 #endif /* MODULE */
+
+module_init(pm3fb_init);
+module_exit(pm3fb_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
index 76e6ce3..a0e22ac 100644
--- a/drivers/video/riva/rivafb-i2c.c
+++ b/drivers/video/riva/rivafb-i2c.c
@@ -70,8 +70,6 @@
 	if (VGA_RD08(par->riva.PCIO, 0x3d5) & 0x04)
 		val = 1;
 
-	val = VGA_RD08(par->riva.PCIO, 0x3d5);
-
 	return val;
 }
 
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index c287a9a..ca75b3a 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -1,4 +1,5 @@
 menu "Dallas's 1-wire bus"
+	depends on HAS_IOMEM
 
 config W1
 	tristate "Dallas's 1-wire support"
diff --git a/fs/Makefile b/fs/Makefile
index 9edf411..720c29d 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -22,6 +22,10 @@
 obj-$(CONFIG_INOTIFY)		+= inotify.o
 obj-$(CONFIG_INOTIFY_USER)	+= inotify_user.o
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
+obj-$(CONFIG_ANON_INODES)	+= anon_inodes.o
+obj-$(CONFIG_SIGNALFD)		+= signalfd.o
+obj-$(CONFIG_TIMERFD)		+= timerfd.o
+obj-$(CONFIG_EVENTFD)		+= eventfd.o
 obj-$(CONFIG_COMPAT)		+= compat.o compat_ioctl.o
 
 nfsd-$(CONFIG_NFSD)		:= nfsctl.o
diff --git a/fs/afs/afs.h b/fs/afs/afs.h
index 52d0752..2452579 100644
--- a/fs/afs/afs.h
+++ b/fs/afs/afs.h
@@ -16,6 +16,9 @@
 
 #define AFS_MAXCELLNAME	64		/* maximum length of a cell name */
 #define AFS_MAXVOLNAME	64		/* maximum length of a volume name */
+#define AFSNAMEMAX	256		/* maximum length of a filename plus NUL */
+#define AFSPATHMAX	1024		/* maximum length of a pathname plus NUL */
+#define AFSOPAQUEMAX	1024		/* maximum length of an opaque field */
 
 typedef unsigned			afs_volid_t;
 typedef unsigned			afs_vnodeid_t;
@@ -143,4 +146,24 @@
 	time_t			creation;	/* volume creation time */
 };
 
+/*
+ * AFS volume status record
+ */
+struct afs_volume_status {
+	u32			vid;		/* volume ID */
+	u32			parent_id;	/* parent volume ID */
+	u8			online;		/* true if volume currently online and available */
+	u8			in_service;	/* true if volume currently in service */
+	u8			blessed;	/* same as in_service */
+	u8			needs_salvage;	/* true if consistency checking required */
+	u32			type;		/* volume type (afs_voltype_t) */
+	u32			min_quota;	/* minimum space set aside (blocks) */
+	u32			max_quota;	/* maximum space this volume may occupy (blocks) */
+	u32			blocks_in_use;	/* space this volume currently occupies (blocks) */
+	u32			part_blocks_avail; /* space available in volume's partition */
+	u32			part_max_blocks; /* size of volume's partition */
+};
+
+#define AFS_BLOCK_SIZE	1024
+
 #endif /* AFS_H */
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h
index 2198006..a18c374 100644
--- a/fs/afs/afs_fs.h
+++ b/fs/afs/afs_fs.h
@@ -28,9 +28,12 @@
 	FSMAKEDIR		= 141,	/* AFS Create a directory */
 	FSREMOVEDIR		= 142,	/* AFS Remove a directory */
 	FSGIVEUPCALLBACKS	= 147,	/* AFS Discard callback promises */
-	FSGETVOLUMEINFO		= 148,	/* AFS Get root volume information */
+	FSGETVOLUMEINFO		= 148,	/* AFS Get information about a volume */
+	FSGETVOLUMESTATUS	= 149,	/* AFS Get volume status information */
 	FSGETROOTVOLUME		= 151,	/* AFS Get root volume name */
 	FSLOOKUP		= 161,	/* AFS lookup file in directory */
+	FSFETCHDATA64		= 65537, /* AFS Fetch file data */
+	FSSTOREDATA64		= 65538, /* AFS Store file data */
 };
 
 enum AFS_FS_Errors {
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 2fb3127..719af4f 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -497,7 +497,7 @@
 
 	ASSERTCMP(dentry->d_inode, ==, NULL);
 
-	if (dentry->d_name.len > 255) {
+	if (dentry->d_name.len >= AFSNAMEMAX) {
 		_leave(" = -ENAMETOOLONG");
 		return ERR_PTR(-ENAMETOOLONG);
 	}
@@ -736,7 +736,7 @@
 	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
 
 	ret = -ENAMETOOLONG;
-	if (dentry->d_name.len > 255)
+	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	key = afs_request_key(dvnode->volume->cell);
@@ -801,7 +801,7 @@
 	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
 	ret = -ENAMETOOLONG;
-	if (dentry->d_name.len > 255)
+	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	key = afs_request_key(dvnode->volume->cell);
@@ -847,7 +847,7 @@
 	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
 
 	ret = -ENAMETOOLONG;
-	if (dentry->d_name.len > 255)
+	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	key = afs_request_key(dvnode->volume->cell);
@@ -921,7 +921,7 @@
 	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
 
 	ret = -ENAMETOOLONG;
-	if (dentry->d_name.len > 255)
+	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	key = afs_request_key(dvnode->volume->cell);
@@ -990,7 +990,7 @@
 	       dentry->d_name.name);
 
 	ret = -ENAMETOOLONG;
-	if (dentry->d_name.len > 255)
+	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	key = afs_request_key(dvnode->volume->cell);
@@ -1038,11 +1038,11 @@
 	       content);
 
 	ret = -ENAMETOOLONG;
-	if (dentry->d_name.len > 255)
+	if (dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	ret = -EINVAL;
-	if (strlen(content) > 1023)
+	if (strlen(content) >= AFSPATHMAX)
 		goto error;
 
 	key = afs_request_key(dvnode->volume->cell);
@@ -1112,7 +1112,7 @@
 	       new_dentry->d_name.name);
 
 	ret = -ENAMETOOLONG;
-	if (new_dentry->d_name.len > 255)
+	if (new_dentry->d_name.len >= AFSNAMEMAX)
 		goto error;
 
 	key = afs_request_key(orig_dvnode->volume->cell);
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 3e25795..9c0e721 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -236,7 +236,7 @@
 {
 	int ret = 1;
 
-	kenter("{%lu},%lu", page->index, offset);
+	_enter("{%lu},%lu", page->index, offset);
 
 	BUG_ON(!PageLocked(page));
 
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index 025b190..5dff130 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -202,6 +202,29 @@
 }
 
 /*
+ * decode an AFSFetchVolumeStatus block
+ */
+static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
+					    struct afs_volume_status *vs)
+{
+	const __be32 *bp = *_bp;
+
+	vs->vid			= ntohl(*bp++);
+	vs->parent_id		= ntohl(*bp++);
+	vs->online		= ntohl(*bp++);
+	vs->in_service		= ntohl(*bp++);
+	vs->blessed		= ntohl(*bp++);
+	vs->needs_salvage	= ntohl(*bp++);
+	vs->type		= ntohl(*bp++);
+	vs->min_quota		= ntohl(*bp++);
+	vs->max_quota		= ntohl(*bp++);
+	vs->blocks_in_use	= ntohl(*bp++);
+	vs->part_blocks_avail	= ntohl(*bp++);
+	vs->part_max_blocks	= ntohl(*bp++);
+	*_bp = bp;
+}
+
+/*
  * deliver reply data to an FS.FetchStatus
  */
 static int afs_deliver_fs_fetch_status(struct afs_call *call,
@@ -293,9 +316,33 @@
 	case 0:
 		call->offset = 0;
 		call->unmarshall++;
+		if (call->operation_ID != FSFETCHDATA64) {
+			call->unmarshall++;
+			goto no_msw;
+		}
 
-		/* extract the returned data length */
+		/* extract the upper part of the returned data length of an
+		 * FSFETCHDATA64 op (which should always be 0 using this
+		 * client) */
 	case 1:
+		_debug("extract data length (MSW)");
+		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->count = ntohl(call->tmp);
+		_debug("DATA length MSW: %u", call->count);
+		if (call->count > 0)
+			return -EBADMSG;
+		call->offset = 0;
+		call->unmarshall++;
+
+	no_msw:
+		/* extract the returned data length */
+	case 2:
 		_debug("extract data length");
 		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
 		switch (ret) {
@@ -312,7 +359,7 @@
 		call->unmarshall++;
 
 		/* extract the returned data */
-	case 2:
+	case 3:
 		_debug("extract data");
 		if (call->count > 0) {
 			page = call->reply3;
@@ -331,7 +378,7 @@
 		call->unmarshall++;
 
 		/* extract the metadata */
-	case 3:
+	case 4:
 		ret = afs_extract_data(call, skb, last, call->buffer,
 				       (21 + 3 + 6) * 4);
 		switch (ret) {
@@ -349,7 +396,7 @@
 		call->offset = 0;
 		call->unmarshall++;
 
-	case 4:
+	case 5:
 		_debug("trailer");
 		if (skb->len != 0)
 			return -EBADMSG;
@@ -381,6 +428,56 @@
 	.destructor	= afs_flat_call_destructor,
 };
 
+static const struct afs_call_type afs_RXFSFetchData64 = {
+	.name		= "FS.FetchData64",
+	.deliver	= afs_deliver_fs_fetch_data,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * fetch data from a very large file
+ */
+static int afs_fs_fetch_data64(struct afs_server *server,
+			       struct key *key,
+			       struct afs_vnode *vnode,
+			       off_t offset, size_t length,
+			       struct page *buffer,
+			       const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter("");
+
+	ASSERTCMP(length, <, ULONG_MAX);
+
+	call = afs_alloc_flat_call(&afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->reply2 = NULL; /* volsync */
+	call->reply3 = buffer;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+	call->operation_ID = FSFETCHDATA64;
+
+	/* marshall the parameters */
+	bp = call->request;
+	bp[0] = htonl(FSFETCHDATA64);
+	bp[1] = htonl(vnode->fid.vid);
+	bp[2] = htonl(vnode->fid.vnode);
+	bp[3] = htonl(vnode->fid.unique);
+	bp[4] = htonl(upper_32_bits(offset));
+	bp[5] = htonl((u32) offset);
+	bp[6] = 0;
+	bp[7] = htonl((u32) length);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
 /*
  * fetch data from a file
  */
@@ -394,6 +491,10 @@
 	struct afs_call *call;
 	__be32 *bp;
 
+	if (upper_32_bits(offset) || upper_32_bits(offset + length))
+		return afs_fs_fetch_data64(server, key, vnode, offset, length,
+					   buffer, wait_mode);
+
 	_enter("");
 
 	call = afs_alloc_flat_call(&afs_RXFSFetchData, 24, (21 + 3 + 6) * 4);
@@ -406,6 +507,7 @@
 	call->reply3 = buffer;
 	call->service_id = FS_SERVICE;
 	call->port = htons(AFS_FS_PORT);
+	call->operation_ID = FSFETCHDATA;
 
 	/* marshall the parameters */
 	bp = call->request;
@@ -1032,6 +1134,73 @@
 	.destructor	= afs_flat_call_destructor,
 };
 
+static const struct afs_call_type afs_RXFSStoreData64 = {
+	.name		= "FS.StoreData64",
+	.deliver	= afs_deliver_fs_store_data,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * store a set of pages to a very large file
+ */
+static int afs_fs_store_data64(struct afs_server *server,
+			       struct afs_writeback *wb,
+			       pgoff_t first, pgoff_t last,
+			       unsigned offset, unsigned to,
+			       loff_t size, loff_t pos, loff_t i_size,
+			       const struct afs_wait_mode *wait_mode)
+{
+	struct afs_vnode *vnode = wb->vnode;
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter(",%x,{%x:%u},,",
+	       key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
+
+	call = afs_alloc_flat_call(&afs_RXFSStoreData64,
+				   (4 + 6 + 3 * 2) * 4,
+				   (21 + 6) * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->wb = wb;
+	call->key = wb->key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+	call->mapping = vnode->vfs_inode.i_mapping;
+	call->first = first;
+	call->last = last;
+	call->first_offset = offset;
+	call->last_to = to;
+	call->send_pages = true;
+	call->store_version = vnode->status.data_version + 1;
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSSTOREDATA64);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+
+	*bp++ = 0; /* mask */
+	*bp++ = 0; /* mtime */
+	*bp++ = 0; /* owner */
+	*bp++ = 0; /* group */
+	*bp++ = 0; /* unix mode */
+	*bp++ = 0; /* segment size */
+
+	*bp++ = htonl(pos >> 32);
+	*bp++ = htonl((u32) pos);
+	*bp++ = htonl(size >> 32);
+	*bp++ = htonl((u32) size);
+	*bp++ = htonl(i_size >> 32);
+	*bp++ = htonl((u32) i_size);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
 /*
  * store a set of pages
  */
@@ -1062,7 +1231,9 @@
 	       (unsigned long long) size, (unsigned long long) pos,
 	       (unsigned long long) i_size);
 
-	BUG_ON(i_size > 0xffffffff); // TODO: use 64-bit store
+	if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
+		return afs_fs_store_data64(server, wb, first, last, offset, to,
+					   size, pos, i_size, wait_mode);
 
 	call = afs_alloc_flat_call(&afs_RXFSStoreData,
 				   (4 + 6 + 3) * 4,
@@ -1158,6 +1329,61 @@
 	.destructor	= afs_flat_call_destructor,
 };
 
+static const struct afs_call_type afs_RXFSStoreData64_as_Status = {
+	.name		= "FS.StoreData64",
+	.deliver	= afs_deliver_fs_store_status,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_flat_call_destructor,
+};
+
+/*
+ * set the attributes on a very large file, using FS.StoreData rather than
+ * FS.StoreStatus so as to alter the file size also
+ */
+static int afs_fs_setattr_size64(struct afs_server *server, struct key *key,
+				 struct afs_vnode *vnode, struct iattr *attr,
+				 const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+
+	_enter(",%x,{%x:%u},,",
+	       key_serial(key), vnode->fid.vid, vnode->fid.vnode);
+
+	ASSERT(attr->ia_valid & ATTR_SIZE);
+
+	call = afs_alloc_flat_call(&afs_RXFSStoreData64_as_Status,
+				   (4 + 6 + 3 * 2) * 4,
+				   (21 + 6) * 4);
+	if (!call)
+		return -ENOMEM;
+
+	call->key = key;
+	call->reply = vnode;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+	call->store_version = vnode->status.data_version + 1;
+	call->operation_ID = FSSTOREDATA;
+
+	/* marshall the parameters */
+	bp = call->request;
+	*bp++ = htonl(FSSTOREDATA64);
+	*bp++ = htonl(vnode->fid.vid);
+	*bp++ = htonl(vnode->fid.vnode);
+	*bp++ = htonl(vnode->fid.unique);
+
+	xdr_encode_AFS_StoreStatus(&bp, attr);
+
+	*bp++ = 0;				/* position of start of write */
+	*bp++ = 0;
+	*bp++ = 0;				/* size of write */
+	*bp++ = 0;
+	*bp++ = htonl(attr->ia_size >> 32);	/* new file length */
+	*bp++ = htonl((u32) attr->ia_size);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
+
 /*
  * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus
  * so as to alter the file size also
@@ -1173,7 +1399,9 @@
 	       key_serial(key), vnode->fid.vid, vnode->fid.vnode);
 
 	ASSERT(attr->ia_valid & ATTR_SIZE);
-	ASSERTCMP(attr->ia_size, <=, 0xffffffff); // TODO: use 64-bit store
+	if (attr->ia_size >> 32)
+		return afs_fs_setattr_size64(server, key, vnode, attr,
+					     wait_mode);
 
 	call = afs_alloc_flat_call(&afs_RXFSStoreData_as_Status,
 				   (4 + 6 + 3) * 4,
@@ -1245,3 +1473,278 @@
 
 	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
 }
+
+/*
+ * deliver reply data to an FS.GetVolumeStatus
+ */
+static int afs_deliver_fs_get_volume_status(struct afs_call *call,
+					    struct sk_buff *skb, bool last)
+{
+	const __be32 *bp;
+	char *p;
+	int ret;
+
+	_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
+
+	switch (call->unmarshall) {
+	case 0:
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the returned status record */
+	case 1:
+		_debug("extract status");
+		ret = afs_extract_data(call, skb, last, call->buffer,
+				       12 * 4);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		bp = call->buffer;
+		xdr_decode_AFSFetchVolumeStatus(&bp, call->reply2);
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the volume name length */
+	case 2:
+		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->count = ntohl(call->tmp);
+		_debug("volname length: %u", call->count);
+		if (call->count >= AFSNAMEMAX)
+			return -EBADMSG;
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the volume name */
+	case 3:
+		_debug("extract volname");
+		if (call->count > 0) {
+			ret = afs_extract_data(call, skb, last, call->reply3,
+					       call->count);
+			switch (ret) {
+			case 0:		break;
+			case -EAGAIN:	return 0;
+			default:	return ret;
+			}
+		}
+
+		p = call->reply3;
+		p[call->count] = 0;
+		_debug("volname '%s'", p);
+
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the volume name padding */
+		if ((call->count & 3) == 0) {
+			call->unmarshall++;
+			goto no_volname_padding;
+		}
+		call->count = 4 - (call->count & 3);
+
+	case 4:
+		ret = afs_extract_data(call, skb, last, call->buffer,
+				       call->count);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->offset = 0;
+		call->unmarshall++;
+	no_volname_padding:
+
+		/* extract the offline message length */
+	case 5:
+		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->count = ntohl(call->tmp);
+		_debug("offline msg length: %u", call->count);
+		if (call->count >= AFSNAMEMAX)
+			return -EBADMSG;
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the offline message */
+	case 6:
+		_debug("extract offline");
+		if (call->count > 0) {
+			ret = afs_extract_data(call, skb, last, call->reply3,
+					       call->count);
+			switch (ret) {
+			case 0:		break;
+			case -EAGAIN:	return 0;
+			default:	return ret;
+			}
+		}
+
+		p = call->reply3;
+		p[call->count] = 0;
+		_debug("offline '%s'", p);
+
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the offline message padding */
+		if ((call->count & 3) == 0) {
+			call->unmarshall++;
+			goto no_offline_padding;
+		}
+		call->count = 4 - (call->count & 3);
+
+	case 7:
+		ret = afs_extract_data(call, skb, last, call->buffer,
+				       call->count);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->offset = 0;
+		call->unmarshall++;
+	no_offline_padding:
+
+		/* extract the message of the day length */
+	case 8:
+		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->count = ntohl(call->tmp);
+		_debug("motd length: %u", call->count);
+		if (call->count >= AFSNAMEMAX)
+			return -EBADMSG;
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the message of the day */
+	case 9:
+		_debug("extract motd");
+		if (call->count > 0) {
+			ret = afs_extract_data(call, skb, last, call->reply3,
+					       call->count);
+			switch (ret) {
+			case 0:		break;
+			case -EAGAIN:	return 0;
+			default:	return ret;
+			}
+		}
+
+		p = call->reply3;
+		p[call->count] = 0;
+		_debug("motd '%s'", p);
+
+		call->offset = 0;
+		call->unmarshall++;
+
+		/* extract the message of the day padding */
+		if ((call->count & 3) == 0) {
+			call->unmarshall++;
+			goto no_motd_padding;
+		}
+		call->count = 4 - (call->count & 3);
+
+	case 10:
+		ret = afs_extract_data(call, skb, last, call->buffer,
+				       call->count);
+		switch (ret) {
+		case 0:		break;
+		case -EAGAIN:	return 0;
+		default:	return ret;
+		}
+
+		call->offset = 0;
+		call->unmarshall++;
+	no_motd_padding:
+
+	case 11:
+		_debug("trailer %d", skb->len);
+		if (skb->len != 0)
+			return -EBADMSG;
+		break;
+	}
+
+	if (!last)
+		return 0;
+
+	_leave(" = 0 [done]");
+	return 0;
+}
+
+/*
+ * destroy an FS.GetVolumeStatus call
+ */
+static void afs_get_volume_status_call_destructor(struct afs_call *call)
+{
+	kfree(call->reply3);
+	call->reply3 = NULL;
+	afs_flat_call_destructor(call);
+}
+
+/*
+ * FS.GetVolumeStatus operation type
+ */
+static const struct afs_call_type afs_RXFSGetVolumeStatus = {
+	.name		= "FS.GetVolumeStatus",
+	.deliver	= afs_deliver_fs_get_volume_status,
+	.abort_to_error	= afs_abort_to_error,
+	.destructor	= afs_get_volume_status_call_destructor,
+};
+
+/*
+ * fetch the status of a volume
+ */
+int afs_fs_get_volume_status(struct afs_server *server,
+			     struct key *key,
+			     struct afs_vnode *vnode,
+			     struct afs_volume_status *vs,
+			     const struct afs_wait_mode *wait_mode)
+{
+	struct afs_call *call;
+	__be32 *bp;
+	void *tmpbuf;
+
+	_enter("");
+
+	tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
+	if (!tmpbuf)
+		return -ENOMEM;
+
+	call = afs_alloc_flat_call(&afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4);
+	if (!call) {
+		kfree(tmpbuf);
+		return -ENOMEM;
+	}
+
+	call->key = key;
+	call->reply = vnode;
+	call->reply2 = vs;
+	call->reply3 = tmpbuf;
+	call->service_id = FS_SERVICE;
+	call->port = htons(AFS_FS_PORT);
+
+	/* marshall the parameters */
+	bp = call->request;
+	bp[0] = htonl(FSGETVOLUMESTATUS);
+	bp[1] = htonl(vnode->fid.vid);
+
+	return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
+}
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 515a5d1..47f5fed 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -209,11 +209,15 @@
  */
 void afs_zap_data(struct afs_vnode *vnode)
 {
-	_enter("zap data {%x:%u}", vnode->fid.vid, vnode->fid.vnode);
+	_enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode);
 
 	/* nuke all the non-dirty pages that aren't locked, mapped or being
-	 * written back */
-	invalidate_remote_inode(&vnode->vfs_inode);
+	 * written back in a regular file and completely discard the pages in a
+	 * directory or symlink */
+	if (S_ISREG(vnode->vfs_inode.i_mode))
+		invalidate_remote_inode(&vnode->vfs_inode);
+	else
+		invalidate_inode_pages2(vnode->vfs_inode.i_mapping);
 }
 
 /*
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index a30d4fa..4953ba5 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -506,6 +506,10 @@
 extern int afs_fs_setattr(struct afs_server *, struct key *,
 			  struct afs_vnode *, struct iattr *,
 			  const struct afs_wait_mode *);
+extern int afs_fs_get_volume_status(struct afs_server *, struct key *,
+				    struct afs_vnode *,
+				    struct afs_volume_status *,
+				    const struct afs_wait_mode *);
 
 /*
  * inode.c
@@ -672,6 +676,8 @@
 extern int afs_vnode_store_data(struct afs_writeback *, pgoff_t, pgoff_t,
 				unsigned, unsigned);
 extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *);
+extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *,
+				       struct afs_volume_status *);
 
 /*
  * volume.c
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 04189c4..1b36f45 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -294,7 +294,7 @@
 			put_page(pages[loop]);
 		if (ret < 0)
 			break;
-	} while (first < last);
+	} while (first <= last);
 
 	_leave(" = %d", ret);
 	return ret;
diff --git a/fs/afs/super.c b/fs/afs/super.c
index d24be33..579af63 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -21,22 +21,20 @@
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/parser.h>
+#include <linux/statfs.h>
 #include "internal.h"
 
 #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
 
 static void afs_i_init_once(void *foo, struct kmem_cache *cachep,
 			    unsigned long flags);
-
 static int afs_get_sb(struct file_system_type *fs_type,
 		      int flags, const char *dev_name,
 		      void *data, struct vfsmount *mnt);
-
 static struct inode *afs_alloc_inode(struct super_block *sb);
-
 static void afs_put_super(struct super_block *sb);
-
 static void afs_destroy_inode(struct inode *inode);
+static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
 
 struct file_system_type afs_fs_type = {
 	.owner		= THIS_MODULE,
@@ -47,7 +45,7 @@
 };
 
 static const struct super_operations afs_super_ops = {
-	.statfs		= simple_statfs,
+	.statfs		= afs_statfs,
 	.alloc_inode	= afs_alloc_inode,
 	.drop_inode	= generic_delete_inode,
 	.write_inode	= afs_write_inode,
@@ -488,6 +486,7 @@
 	vnode->flags		= 1 << AFS_VNODE_UNSET;
 	vnode->cb_promised	= false;
 
+	_leave(" = %p", &vnode->vfs_inode);
 	return &vnode->vfs_inode;
 }
 
@@ -498,7 +497,7 @@
 {
 	struct afs_vnode *vnode = AFS_FS_I(inode);
 
-	_enter("{%lu}", inode->i_ino);
+	_enter("%p{%x:%u}", inode, vnode->fid.vid, vnode->fid.vnode);
 
 	_debug("DESTROY INODE %p", inode);
 
@@ -507,3 +506,36 @@
 	kmem_cache_free(afs_inode_cachep, vnode);
 	atomic_dec(&afs_count_active_inodes);
 }
+
+/*
+ * return information about an AFS volume
+ */
+static int afs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+	struct afs_volume_status vs;
+	struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
+	struct key *key;
+	int ret;
+
+	key = afs_request_key(vnode->volume->cell);
+	if (IS_ERR(key))
+		return PTR_ERR(key);
+
+	ret = afs_vnode_get_volume_status(vnode, key, &vs);
+	key_put(key);
+	if (ret < 0) {
+		_leave(" = %d", ret);
+		return ret;
+	}
+
+	buf->f_type	= dentry->d_sb->s_magic;
+	buf->f_bsize	= AFS_BLOCK_SIZE;
+	buf->f_namelen	= AFSNAMEMAX - 1;
+
+	if (vs.max_quota == 0)
+		buf->f_blocks = vs.part_max_blocks;
+	else
+		buf->f_blocks = vs.max_quota;
+	buf->f_bavail = buf->f_bfree = buf->f_blocks - vs.blocks_in_use;
+	return 0;
+}
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c
index ec81466..c36c98c 100644
--- a/fs/afs/vnode.c
+++ b/fs/afs/vnode.c
@@ -175,24 +175,33 @@
 {
 	struct afs_server *server;
 
+	_enter("{%p}", vnode->server);
+
 	set_bit(AFS_VNODE_DELETED, &vnode->flags);
 
 	server = vnode->server;
-	if (vnode->cb_promised) {
-		spin_lock(&server->cb_lock);
+	if (server) {
 		if (vnode->cb_promised) {
-			rb_erase(&vnode->cb_promise, &server->cb_promises);
-			vnode->cb_promised = false;
+			spin_lock(&server->cb_lock);
+			if (vnode->cb_promised) {
+				rb_erase(&vnode->cb_promise,
+					 &server->cb_promises);
+				vnode->cb_promised = false;
+			}
+			spin_unlock(&server->cb_lock);
 		}
-		spin_unlock(&server->cb_lock);
+
+		spin_lock(&server->fs_lock);
+		rb_erase(&vnode->server_rb, &server->fs_vnodes);
+		spin_unlock(&server->fs_lock);
+
+		vnode->server = NULL;
+		afs_put_server(server);
+	} else {
+		ASSERT(!vnode->cb_promised);
 	}
 
-	spin_lock(&vnode->server->fs_lock);
-	rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes);
-	spin_unlock(&vnode->server->fs_lock);
-
-	vnode->server = NULL;
-	afs_put_server(server);
+	_leave("");
 }
 
 /*
@@ -225,7 +234,7 @@
  */
 static void afs_vnode_status_update_failed(struct afs_vnode *vnode, int ret)
 {
-	_enter("%p,%d", vnode, ret);
+	_enter("{%x:%u},%d", vnode->fid.vid, vnode->fid.vnode, ret);
 
 	spin_lock(&vnode->lock);
 
@@ -860,3 +869,55 @@
 	spin_unlock(&vnode->lock);
 	return PTR_ERR(server);
 }
+
+/*
+ * get the status of a volume
+ */
+int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key,
+				struct afs_volume_status *vs)
+{
+	struct afs_server *server;
+	int ret;
+
+	_enter("%s{%x:%u.%u},%x,",
+	       vnode->volume->vlocation->vldb.name,
+	       vnode->fid.vid,
+	       vnode->fid.vnode,
+	       vnode->fid.unique,
+	       key_serial(key));
+
+	/* this op will fetch the status */
+	spin_lock(&vnode->lock);
+	vnode->update_cnt++;
+	spin_unlock(&vnode->lock);
+
+	do {
+		/* pick a server to query */
+		server = afs_volume_pick_fileserver(vnode);
+		if (IS_ERR(server))
+			goto no_server;
+
+		_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+		ret = afs_fs_get_volume_status(server, key, vnode, vs, &afs_sync_call);
+
+	} while (!afs_volume_release_fileserver(vnode, server, ret));
+
+	/* adjust the flags */
+	if (ret == 0) {
+		afs_vnode_finalise_status_update(vnode, server);
+		afs_put_server(server);
+	} else {
+		afs_vnode_status_update_failed(vnode, ret);
+	}
+
+	_leave(" = %d", ret);
+	return ret;
+
+no_server:
+	spin_lock(&vnode->lock);
+	vnode->update_cnt--;
+	ASSERTCMP(vnode->update_cnt, >=, 0);
+	spin_unlock(&vnode->lock);
+	return PTR_ERR(server);
+}
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 83ff292..28f3751 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -122,7 +122,7 @@
 	if (offset == 0 && to == PAGE_SIZE)
 		return 0;
 
-	p = kmap(page);
+	p = kmap_atomic(page, KM_USER0);
 
 	i_size = i_size_read(&vnode->vfs_inode);
 	pos = (loff_t) page->index << PAGE_SHIFT;
@@ -133,7 +133,7 @@
 			memset(p, 0, offset);
 		if (to < PAGE_SIZE)
 			memset(p + to, 0, PAGE_SIZE - to);
-		kunmap(page);
+		kunmap_atomic(p, KM_USER0);
 		return 0;
 	}
 
@@ -152,7 +152,7 @@
 			memset(p + eof, 0, PAGE_SIZE - eof);
 	}
 
-	kunmap(p);
+	kunmap_atomic(p, KM_USER0);
 
 	ret = 0;
 	if (offset > 0 || eof > to) {
@@ -395,8 +395,9 @@
 		if (n == 0)
 			goto no_more;
 		if (pages[0]->index != start) {
-			for (n--; n >= 0; n--)
-				put_page(pages[n]);
+			do {
+				put_page(pages[--n]);
+			} while (n > 0);
 			goto no_more;
 		}
 
@@ -489,14 +490,6 @@
 
 	_enter("{%lx},", page->index);
 
-	if (wbc->sync_mode != WB_SYNC_NONE)
-		wait_on_page_writeback(page);
-
-	if (PageWriteback(page) || !PageDirty(page)) {
-		unlock_page(page);
-		return 0;
-	}
-
 	wb = (struct afs_writeback *) page_private(page);
 	ASSERT(wb != NULL);
 
@@ -677,7 +670,7 @@
 	pagevec_init(&pv, 0);
 
 	do {
-		_debug("attach %lx-%lx", first, last);
+		_debug("done %lx-%lx", first, last);
 
 		count = last - first + 1;
 		if (count > PAGEVEC_SIZE)
@@ -709,7 +702,7 @@
 		}
 
 		__pagevec_release(&pv);
-	} while (first < last);
+	} while (first <= last);
 
 	_leave("");
 }
diff --git a/fs/aio.c b/fs/aio.c
index ac1c158..dbe699e 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -30,6 +30,7 @@
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
+#include <linux/eventfd.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
@@ -417,6 +418,7 @@
 	req->private = NULL;
 	req->ki_iovec = NULL;
 	INIT_LIST_HEAD(&req->ki_run_list);
+	req->ki_eventfd = ERR_PTR(-EINVAL);
 
 	/* Check if the completion queue has enough free space to
 	 * accept an event from this io.
@@ -458,6 +460,8 @@
 {
 	assert_spin_locked(&ctx->ctx_lock);
 
+	if (!IS_ERR(req->ki_eventfd))
+		fput(req->ki_eventfd);
 	if (req->ki_dtor)
 		req->ki_dtor(req);
 	if (req->ki_iovec != &req->ki_inline_vec)
@@ -942,6 +946,14 @@
 		return 1;
 	}
 
+	/*
+	 * Check if the user asked us to deliver the result through an
+	 * eventfd. The eventfd_signal() function is safe to be called
+	 * from IRQ context.
+	 */
+	if (!IS_ERR(iocb->ki_eventfd))
+		eventfd_signal(iocb->ki_eventfd, 1);
+
 	info = &ctx->ring_info;
 
 	/* add a completion event to the ring buffer.
@@ -1526,8 +1538,7 @@
 	ssize_t ret;
 
 	/* enforce forwards compatibility on users */
-	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
-		     iocb->aio_reserved3)) {
+	if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
 		pr_debug("EINVAL: io_submit: reserve field set\n");
 		return -EINVAL;
 	}
@@ -1551,6 +1562,19 @@
 		fput(file);
 		return -EAGAIN;
 	}
+	if (iocb->aio_flags & IOCB_FLAG_RESFD) {
+		/*
+		 * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
+		 * instance of the file* now. The file descriptor must be
+		 * an eventfd() fd, and will be signaled for each completed
+		 * event using the eventfd_signal() function.
+		 */
+		req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
+		if (unlikely(IS_ERR(req->ki_eventfd))) {
+			ret = PTR_ERR(req->ki_eventfd);
+			goto out_put_req;
+		}
+	}
 
 	req->ki_filp = file;
 	ret = put_user(req->ki_key, &user_iocb->aio_key);
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
new file mode 100644
index 0000000..40fe3a3
--- /dev/null
+++ b/fs/anon_inodes.c
@@ -0,0 +1,200 @@
+/*
+ *  fs/anon_inodes.c
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ *  Thanks to Arnd Bergmann for code review and suggestions.
+ *  More changes for Thomas Gleixner suggestions.
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/mount.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/magic.h>
+#include <linux/anon_inodes.h>
+
+#include <asm/uaccess.h>
+
+static struct vfsmount *anon_inode_mnt __read_mostly;
+static struct inode *anon_inode_inode;
+static const struct file_operations anon_inode_fops;
+
+static int anon_inodefs_get_sb(struct file_system_type *fs_type, int flags,
+			       const char *dev_name, void *data,
+			       struct vfsmount *mnt)
+{
+	return get_sb_pseudo(fs_type, "anon_inode:", NULL, ANON_INODE_FS_MAGIC,
+			     mnt);
+}
+
+static int anon_inodefs_delete_dentry(struct dentry *dentry)
+{
+	/*
+	 * We faked vfs to believe the dentry was hashed when we created it.
+	 * Now we restore the flag so that dput() will work correctly.
+	 */
+	dentry->d_flags |= DCACHE_UNHASHED;
+	return 1;
+}
+
+static struct file_system_type anon_inode_fs_type = {
+	.name		= "anon_inodefs",
+	.get_sb		= anon_inodefs_get_sb,
+	.kill_sb	= kill_anon_super,
+};
+static struct dentry_operations anon_inodefs_dentry_operations = {
+	.d_delete	= anon_inodefs_delete_dentry,
+};
+
+/**
+ * anon_inode_getfd - creates a new file instance by hooking it up to and
+ *                    anonymous inode, and a dentry that describe the "class"
+ *                    of the file
+ *
+ * @pfd:     [out]   pointer to the file descriptor
+ * @dpinode: [out]   pointer to the inode
+ * @pfile:   [out]   pointer to the file struct
+ * @name:    [in]    name of the "class" of the new file
+ * @fops     [in]    file operations for the new file
+ * @priv     [in]    private data for the new file (will be file's private_data)
+ *
+ * Creates a new file by hooking it on a single inode. This is useful for files
+ * that do not need to have a full-fledged inode in order to operate correctly.
+ * All the files created with anon_inode_getfd() will share a single inode, by
+ * hence saving memory and avoiding code duplication for the file/inode/dentry
+ * setup.
+ */
+int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+		     const char *name, const struct file_operations *fops,
+		     void *priv)
+{
+	struct qstr this;
+	struct dentry *dentry;
+	struct inode *inode;
+	struct file *file;
+	int error, fd;
+
+	if (IS_ERR(anon_inode_inode))
+		return -ENODEV;
+	file = get_empty_filp();
+	if (!file)
+		return -ENFILE;
+
+	inode = igrab(anon_inode_inode);
+	if (IS_ERR(inode)) {
+		error = PTR_ERR(inode);
+		goto err_put_filp;
+	}
+
+	error = get_unused_fd();
+	if (error < 0)
+		goto err_iput;
+	fd = error;
+
+	/*
+	 * Link the inode to a directory entry by creating a unique name
+	 * using the inode sequence number.
+	 */
+	error = -ENOMEM;
+	this.name = name;
+	this.len = strlen(name);
+	this.hash = 0;
+	dentry = d_alloc(anon_inode_mnt->mnt_sb->s_root, &this);
+	if (!dentry)
+		goto err_put_unused_fd;
+	dentry->d_op = &anon_inodefs_dentry_operations;
+	/* Do not publish this dentry inside the global dentry hash table */
+	dentry->d_flags &= ~DCACHE_UNHASHED;
+	d_instantiate(dentry, inode);
+
+	file->f_path.mnt = mntget(anon_inode_mnt);
+	file->f_path.dentry = dentry;
+	file->f_mapping = inode->i_mapping;
+
+	file->f_pos = 0;
+	file->f_flags = O_RDWR;
+	file->f_op = fops;
+	file->f_mode = FMODE_READ | FMODE_WRITE;
+	file->f_version = 0;
+	file->private_data = priv;
+
+	fd_install(fd, file);
+
+	*pfd = fd;
+	*pinode = inode;
+	*pfile = file;
+	return 0;
+
+err_put_unused_fd:
+	put_unused_fd(fd);
+err_iput:
+	iput(inode);
+err_put_filp:
+	put_filp(file);
+	return error;
+}
+
+/*
+ * A single inode exist for all anon_inode files. Contrary to pipes,
+ * anon_inode inodes has no per-instance data associated, so we can avoid
+ * the allocation of multiple of them.
+ */
+static struct inode *anon_inode_mkinode(void)
+{
+	struct inode *inode = new_inode(anon_inode_mnt->mnt_sb);
+
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	inode->i_fop = &anon_inode_fops;
+
+	/*
+	 * Mark the inode dirty from the very beginning,
+	 * that way it will never be moved to the dirty
+	 * list because mark_inode_dirty() will think
+	 * that it already _is_ on the dirty list.
+	 */
+	inode->i_state = I_DIRTY;
+	inode->i_mode = S_IRUSR | S_IWUSR;
+	inode->i_uid = current->fsuid;
+	inode->i_gid = current->fsgid;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+	return inode;
+}
+
+static int __init anon_inode_init(void)
+{
+	int error;
+
+	error = register_filesystem(&anon_inode_fs_type);
+	if (error)
+		goto err_exit;
+	anon_inode_mnt = kern_mount(&anon_inode_fs_type);
+	if (IS_ERR(anon_inode_mnt)) {
+		error = PTR_ERR(anon_inode_mnt);
+		goto err_unregister_filesystem;
+	}
+	anon_inode_inode = anon_inode_mkinode();
+	if (IS_ERR(anon_inode_inode)) {
+		error = PTR_ERR(anon_inode_inode);
+		goto err_mntput;
+	}
+
+	return 0;
+
+err_mntput:
+	mntput(anon_inode_mnt);
+err_unregister_filesystem:
+	unregister_filesystem(&anon_inode_fs_type);
+err_exit:
+	panic(KERN_ERR "anon_inode_init() failed (%d)\n", error);
+}
+
+fs_initcall(anon_inode_init);
+
diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h
index 4ef5444..8b4cca3 100644
--- a/fs/autofs/autofs_i.h
+++ b/fs/autofs/autofs_i.h
@@ -101,7 +101,7 @@
 struct autofs_sb_info {
 	u32 magic;
 	struct file *pipe;
-	pid_t oz_pgrp;
+	struct pid *oz_pgrp;
 	int catatonic;
 	struct super_block *sb;
 	unsigned long exp_timeout;
@@ -122,7 +122,7 @@
    filesystem without "magic".) */
 
 static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
-	return sbi->catatonic || process_group(current) == sbi->oz_pgrp;
+	return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
 }
 
 /* Hash operations */
diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c
index aa0b61f..e7204d7 100644
--- a/fs/autofs/inode.c
+++ b/fs/autofs/inode.c
@@ -34,12 +34,14 @@
 	if (!sbi)
 		goto out_kill_sb;
 
-	if ( !sbi->catatonic )
+	if (!sbi->catatonic)
 		autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
 
+	put_pid(sbi->oz_pgrp);
+
 	autofs_hash_nuke(sbi);
-	for ( n = 0 ; n < AUTOFS_MAX_SYMLINKS ; n++ ) {
-		if ( test_bit(n, sbi->symlink_bitmap) )
+	for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) {
+		if (test_bit(n, sbi->symlink_bitmap))
 			kfree(sbi->symlink[n].data);
 	}
 
@@ -69,7 +71,8 @@
 	{Opt_err, NULL}
 };
 
-static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid, pid_t *pgrp, int *minproto, int *maxproto)
+static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
+		pid_t *pgrp, int *minproto, int *maxproto)
 {
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
@@ -138,9 +141,10 @@
 	int pipefd;
 	struct autofs_sb_info *sbi;
 	int minproto, maxproto;
+	pid_t pgid;
 
 	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if ( !sbi )
+	if (!sbi)
 		goto fail_unlock;
 	DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
 
@@ -149,7 +153,6 @@
 	sbi->pipe = NULL;
 	sbi->catatonic = 1;
 	sbi->exp_timeout = 0;
-	sbi->oz_pgrp = process_group(current);
 	autofs_initialize_hash(&sbi->dirhash);
 	sbi->queues = NULL;
 	memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN);
@@ -169,26 +172,36 @@
 		goto fail_iput;
 
 	/* Can this call block?  - WTF cares? s is locked. */
-	if ( parse_options(data,&pipefd,&root_inode->i_uid,&root_inode->i_gid,&sbi->oz_pgrp,&minproto,&maxproto) ) {
+	if (parse_options(data, &pipefd, &root_inode->i_uid,
+				&root_inode->i_gid, &pgid, &minproto,
+				&maxproto)) {
 		printk("autofs: called with bogus options\n");
 		goto fail_dput;
 	}
 
 	/* Couldn't this be tested earlier? */
-	if ( minproto > AUTOFS_PROTO_VERSION || 
-	     maxproto < AUTOFS_PROTO_VERSION ) {
+	if (minproto > AUTOFS_PROTO_VERSION ||
+	     maxproto < AUTOFS_PROTO_VERSION) {
 		printk("autofs: kernel does not match daemon version\n");
 		goto fail_dput;
 	}
 
-	DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp));
-	pipe = fget(pipefd);
-	
-	if ( !pipe ) {
-		printk("autofs: could not open pipe file descriptor\n");
+	DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid));
+	sbi->oz_pgrp = find_get_pid(pgid);
+
+	if (!sbi->oz_pgrp) {
+		printk("autofs: could not find process group %d\n", pgid);
 		goto fail_dput;
 	}
-	if ( !pipe->f_op || !pipe->f_op->write )
+
+	pipe = fget(pipefd);
+	
+	if (!pipe) {
+		printk("autofs: could not open pipe file descriptor\n");
+		goto fail_put_pid;
+	}
+
+	if (!pipe->f_op || !pipe->f_op->write)
 		goto fail_fput;
 	sbi->pipe = pipe;
 	sbi->catatonic = 0;
@@ -202,6 +215,8 @@
 fail_fput:
 	printk("autofs: pipe file descriptor does not contain proper ops\n");
 	fput(pipe);
+fail_put_pid:
+	put_pid(sbi->oz_pgrp);
 fail_dput:
 	dput(root);
 	goto fail_free;
@@ -230,7 +245,7 @@
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 	inode->i_blocks = 0;
 
-	if ( ino == AUTOFS_ROOT_INO ) {
+	if (ino == AUTOFS_ROOT_INO) {
 		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
 		inode->i_op = &autofs_root_inode_operations;
 		inode->i_fop = &autofs_root_operations;
@@ -241,12 +256,12 @@
 	inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
 	inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
 	
-	if ( ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO ) {
+	if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) {
 		/* Symlink inode - should be in symlink list */
 		struct autofs_symlink *sl;
 
 		n = ino - AUTOFS_FIRST_SYMLINK;
-		if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
+		if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
 			printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino);
 			return;
 		}
diff --git a/fs/autofs/root.c b/fs/autofs/root.c
index f259720..c148953 100644
--- a/fs/autofs/root.c
+++ b/fs/autofs/root.c
@@ -67,8 +67,8 @@
 		filp->f_pos = ++nr;
 		/* fall through */
 	default:
-		while ( onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent) ) {
-			if ( !ent->dentry || d_mountpoint(ent->dentry) ) {
+		while (onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent)) {
+			if (!ent->dentry || d_mountpoint(ent->dentry)) {
 				if (filldir(dirent,ent->name,ent->len,onr,ent->ino,DT_UNKNOWN) < 0)
 					goto out;
 				filp->f_pos = nr;
@@ -88,10 +88,10 @@
 	struct autofs_dir_ent *ent;
 	int status = 0;
 
-	if ( !(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) ) {
+	if (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) {
 		do {
-			if ( status && dentry->d_inode ) {
-				if ( status != -ENOENT )
+			if (status && dentry->d_inode) {
+				if (status != -ENOENT)
 					printk("autofs warning: lookup failure on positive dentry, status = %d, name = %s\n", status, dentry->d_name.name);
 				return 0; /* Try to get the kernel to invalidate this dentry */
 			}
@@ -106,7 +106,7 @@
 				return 1;
 			}
 			status = autofs_wait(sbi, &dentry->d_name);
-		} while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)) );
+		} while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)));
 	}
 
 	/* Abuse this field as a pointer to the directory entry, used to
@@ -124,13 +124,13 @@
 
 	/* If this is a directory that isn't a mount point, bitch at the
 	   daemon and fix it in user space */
-	if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) {
+	if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
 		return !autofs_wait(sbi, &dentry->d_name);
 	}
 
 	/* We don't update the usages for the autofs daemon itself, this
 	   is necessary for recursive autofs mounts */
-	if ( !autofs_oz_mode(sbi) ) {
+	if (!autofs_oz_mode(sbi)) {
 		autofs_update_usage(&sbi->dirhash,ent);
 	}
 
@@ -157,7 +157,7 @@
 	sbi = autofs_sbi(dir->i_sb);
 
 	/* Pending dentry */
-	if ( dentry->d_flags & DCACHE_AUTOFS_PENDING ) {
+	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
 		if (autofs_oz_mode(sbi))
 			res = 1;
 		else
@@ -173,7 +173,7 @@
 	}
 		
 	/* Check for a non-mountpoint directory */
-	if ( S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry) ) {
+	if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
 		if (autofs_oz_mode(sbi))
 			res = 1;
 		else
@@ -183,9 +183,9 @@
 	}
 
 	/* Update the usage list */
-	if ( !autofs_oz_mode(sbi) ) {
+	if (!autofs_oz_mode(sbi)) {
 		ent = (struct autofs_dir_ent *) dentry->d_time;
-		if ( ent )
+		if (ent)
 			autofs_update_usage(&sbi->dirhash,ent);
 	}
 	unlock_kernel();
@@ -213,8 +213,10 @@
 	sbi = autofs_sbi(dir->i_sb);
 
 	oz_mode = autofs_oz_mode(sbi);
-	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
-		 current->pid, process_group(current), sbi->catatonic, oz_mode));
+	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, "
+				"oz_mode = %d\n", pid_nr(task_pid(current)),
+				process_group(current), sbi->catatonic,
+				oz_mode));
 
 	/*
 	 * Mark the dentry incomplete, but add it. This is needed so
@@ -258,7 +260,7 @@
 	 * doesn't do the right thing for all system calls, but it should
 	 * be OK for the operations we permit from an autofs.
 	 */
-	if ( dentry->d_inode && d_unhashed(dentry) )
+	if (dentry->d_inode && d_unhashed(dentry))
 		return ERR_PTR(-ENOENT);
 
 	return NULL;
@@ -277,18 +279,18 @@
 	autofs_say(dentry->d_name.name,dentry->d_name.len);
 
 	lock_kernel();
-	if ( !autofs_oz_mode(sbi) ) {
+	if (!autofs_oz_mode(sbi)) {
 		unlock_kernel();
 		return -EACCES;
 	}
 
-	if ( autofs_hash_lookup(dh, &dentry->d_name) ) {
+	if (autofs_hash_lookup(dh, &dentry->d_name)) {
 		unlock_kernel();
 		return -EEXIST;
 	}
 
 	n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
-	if ( n >= AUTOFS_MAX_SYMLINKS ) {
+	if (n >= AUTOFS_MAX_SYMLINKS) {
 		unlock_kernel();
 		return -ENOSPC;
 	}
@@ -297,14 +299,14 @@
 	sl = &sbi->symlink[n];
 	sl->len = strlen(symname);
 	sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
-	if ( !sl->data ) {
+	if (!sl->data) {
 		clear_bit(n,sbi->symlink_bitmap);
 		unlock_kernel();
 		return -ENOSPC;
 	}
 
 	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if ( !ent ) {
+	if (!ent) {
 		kfree(sl->data);
 		clear_bit(n,sbi->symlink_bitmap);
 		unlock_kernel();
@@ -312,7 +314,7 @@
 	}
 
 	ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
-	if ( !ent->name ) {
+	if (!ent->name) {
 		kfree(sl->data);
 		kfree(ent);
 		clear_bit(n,sbi->symlink_bitmap);
@@ -354,23 +356,23 @@
 
 	/* This allows root to remove symlinks */
 	lock_kernel();
-	if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) ) {
+	if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) {
 		unlock_kernel();
 		return -EACCES;
 	}
 
 	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if ( !ent ) {
+	if (!ent) {
 		unlock_kernel();
 		return -ENOENT;
 	}
 
 	n = ent->ino - AUTOFS_FIRST_SYMLINK;
-	if ( n >= AUTOFS_MAX_SYMLINKS ) {
+	if (n >= AUTOFS_MAX_SYMLINKS) {
 		unlock_kernel();
 		return -EISDIR;	/* It's a directory, dummy */
 	}
-	if ( !test_bit(n,sbi->symlink_bitmap) ) {
+	if (!test_bit(n,sbi->symlink_bitmap)) {
 		unlock_kernel();
 		return -EINVAL;	/* Nonexistent symlink?  Shouldn't happen */
 	}
@@ -392,23 +394,23 @@
 	struct autofs_dir_ent *ent;
 
 	lock_kernel();
-	if ( !autofs_oz_mode(sbi) ) {
+	if (!autofs_oz_mode(sbi)) {
 		unlock_kernel();
 		return -EACCES;
 	}
 
 	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if ( !ent ) {
+	if (!ent) {
 		unlock_kernel();
 		return -ENOENT;
 	}
 
-	if ( (unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO ) {
+	if ((unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO) {
 		unlock_kernel();
 		return -ENOTDIR; /* Not a directory */
 	}
 
-	if ( ent->dentry != dentry ) {
+	if (ent->dentry != dentry) {
 		printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name);
 	}
 
@@ -429,18 +431,18 @@
 	ino_t ino;
 
 	lock_kernel();
-	if ( !autofs_oz_mode(sbi) ) {
+	if (!autofs_oz_mode(sbi)) {
 		unlock_kernel();
 		return -EACCES;
 	}
 
 	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if ( ent ) {
+	if (ent) {
 		unlock_kernel();
 		return -EEXIST;
 	}
 
-	if ( sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO ) {
+	if (sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO) {
 		printk("autofs: Out of inode numbers -- what the heck did you do??\n");
 		unlock_kernel();
 		return -ENOSPC;
@@ -448,13 +450,13 @@
 	ino = sbi->next_dir_ino++;
 
 	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if ( !ent ) {
+	if (!ent) {
 		unlock_kernel();
 		return -ENOSPC;
 	}
 
 	ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
-	if ( !ent->name ) {
+	if (!ent->name) {
 		kfree(ent);
 		unlock_kernel();
 		return -ENOSPC;
@@ -483,7 +485,7 @@
 	    put_user(sbi->exp_timeout / HZ, p))
 		return -EFAULT;
 
-	if ( ntimeout > ULONG_MAX/HZ )
+	if (ntimeout > ULONG_MAX/HZ)
 		sbi->exp_timeout = 0;
 	else
 		sbi->exp_timeout = ntimeout * HZ;
@@ -511,15 +513,14 @@
 	pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
 	pkt.hdr.type = autofs_ptype_expire;
 
-	if ( !sbi->exp_timeout ||
-	     !(ent = autofs_expire(sb,sbi,mnt)) )
+	if (!sbi->exp_timeout || !(ent = autofs_expire(sb,sbi,mnt)))
 		return -EAGAIN;
 
 	pkt.len = ent->len;
 	memcpy(pkt.name, ent->name, pkt.len);
 	pkt.name[pkt.len] = '\0';
 
-	if ( copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)) )
+	if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
 		return -EFAULT;
 
 	return 0;
@@ -537,11 +538,11 @@
 
 	DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,process_group(current)));
 
-	if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
-	     _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
+	if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
+	     _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
 		return -ENOTTY;
 	
-	if ( !autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+	if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	
 	switch(cmd) {
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 5769a2f..692364e8 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -218,8 +218,7 @@
 };
 
 static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
-			 pid_t *pgrp, unsigned int *type,
-			 int *minproto, int *maxproto)
+		pid_t *pgrp, unsigned int *type, int *minproto, int *maxproto)
 {
 	char *p;
 	substring_t args[MAX_OPT_ARGS];
@@ -314,7 +313,7 @@
 	struct autofs_info *ino;
 
 	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
-	if ( !sbi )
+	if (!sbi)
 		goto fail_unlock;
 	DPRINTK("starting up, sbi = %p",sbi);
 
@@ -363,10 +362,9 @@
 	root->d_fsdata = ino;
 
 	/* Can this call block? */
-	if (parse_options(data, &pipefd,
-			  &root_inode->i_uid, &root_inode->i_gid,
-			  &sbi->oz_pgrp, &sbi->type,
-			  &sbi->min_proto, &sbi->max_proto)) {
+	if (parse_options(data, &pipefd, &root_inode->i_uid, &root_inode->i_gid,
+				&sbi->oz_pgrp, &sbi->type, &sbi->min_proto,
+				&sbi->max_proto)) {
 		printk("autofs: called with bogus options\n");
 		goto fail_dput;
 	}
@@ -396,11 +394,11 @@
 	DPRINTK("pipe fd = %d, pgrp = %u", pipefd, sbi->oz_pgrp);
 	pipe = fget(pipefd);
 	
-	if ( !pipe ) {
+	if (!pipe) {
 		printk("autofs: could not open pipe file descriptor\n");
 		goto fail_dput;
 	}
-	if ( !pipe->f_op || !pipe->f_op->write )
+	if (!pipe->f_op || !pipe->f_op->write)
 		goto fail_fput;
 	sbi->pipe = pipe;
 	sbi->pipefd = pipefd;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 15170f4..2d4c8a3 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -759,7 +759,7 @@
 	struct autofs_info *p_ino;
 	
 	/* This allows root to remove symlinks */
-	if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+	if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
 	if (atomic_dec_and_test(&ino->count)) {
@@ -833,7 +833,7 @@
 	struct autofs_info *p_ino;
 	struct inode *inode;
 
-	if ( !autofs4_oz_mode(sbi) )
+	if (!autofs4_oz_mode(sbi))
 		return -EACCES;
 
 	DPRINTK("dentry %p, creating %.*s",
@@ -871,11 +871,11 @@
 	int rv;
 	unsigned long ntimeout;
 
-	if ( (rv = get_user(ntimeout, p)) ||
-	     (rv = put_user(sbi->exp_timeout/HZ, p)) )
+	if ((rv = get_user(ntimeout, p)) ||
+	     (rv = put_user(sbi->exp_timeout/HZ, p)))
 		return rv;
 
-	if ( ntimeout > ULONG_MAX/HZ )
+	if (ntimeout > ULONG_MAX/HZ)
 		sbi->exp_timeout = 0;
 	else
 		sbi->exp_timeout = ntimeout * HZ;
@@ -906,7 +906,7 @@
 	DPRINTK("returning %d", sbi->needs_reghost);
 
 	status = put_user(sbi->needs_reghost, p);
-	if ( status )
+	if (status)
 		return status;
 
 	sbi->needs_reghost = 0;
@@ -975,11 +975,11 @@
 	DPRINTK("cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u",
 		cmd,arg,sbi,process_group(current));
 
-	if ( _IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
-	     _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT )
+	if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
+	     _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
 		return -ENOTTY;
 	
-	if ( !autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN) )
+	if (!autofs4_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	
 	switch(cmd) {
diff --git a/fs/compat.c b/fs/compat.c
index 9cf75df..7b21b0a 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -46,6 +46,7 @@
 #include <linux/tsacct_kern.h>
 #include <linux/security.h>
 #include <linux/highmem.h>
+#include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/mm.h>
 #include <linux/eventpoll.h>
@@ -2199,3 +2200,51 @@
 #endif /* TIF_RESTORE_SIGMASK */
 
 #endif /* CONFIG_EPOLL */
+
+#ifdef CONFIG_SIGNALFD
+
+asmlinkage long compat_sys_signalfd(int ufd,
+				    const compat_sigset_t __user *sigmask,
+				    compat_size_t sigsetsize)
+{
+	compat_sigset_t ss32;
+	sigset_t tmp;
+	sigset_t __user *ksigmask;
+
+	if (sigsetsize != sizeof(compat_sigset_t))
+		return -EINVAL;
+	if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
+		return -EFAULT;
+	sigset_from_compat(&tmp, &ss32);
+	ksigmask = compat_alloc_user_space(sizeof(sigset_t));
+	if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
+		return -EFAULT;
+
+	return sys_signalfd(ufd, ksigmask, sizeof(sigset_t));
+}
+
+#endif /* CONFIG_SIGNALFD */
+
+#ifdef CONFIG_TIMERFD
+
+asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags,
+				   const struct compat_itimerspec __user *utmr)
+{
+	long res;
+	struct itimerspec t;
+	struct itimerspec __user *ut;
+
+	res = -EFAULT;
+	if (get_compat_itimerspec(&t, utmr))
+		goto err_exit;
+	ut = compat_alloc_user_space(sizeof(*ut));
+	if (copy_to_user(ut, &t, sizeof(t)) )
+		goto err_exit;
+
+	res = sys_timerfd(ufd, clockid, flags, ut);
+err_exit:
+	return res;
+}
+
+#endif /* CONFIG_TIMERFD */
+
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index d92bc3e..65643de 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -3566,10 +3566,13 @@
 			goto found_handler;
 	}
 
+#ifdef CONFIG_NET
 	if (S_ISSOCK(filp->f_path.dentry->d_inode->i_mode) &&
 	    cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
 		error = siocdevprivate_ioctl(fd, cmd, arg);
-	} else {
+	} else
+#endif
+	{
 		static int count;
 
 		if (++count <= 50)
diff --git a/fs/eventfd.c b/fs/eventfd.c
new file mode 100644
index 0000000..480e2b3
--- /dev/null
+++ b/fs/eventfd.c
@@ -0,0 +1,228 @@
+/*
+ *  fs/eventfd.c
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/anon_inodes.h>
+#include <linux/eventfd.h>
+
+struct eventfd_ctx {
+	spinlock_t lock;
+	wait_queue_head_t wqh;
+	/*
+	 * Every time that a write(2) is performed on an eventfd, the
+	 * value of the __u64 being written is added to "count" and a
+	 * wakeup is performed on "wqh". A read(2) will return the "count"
+	 * value to userspace, and will reset "count" to zero. The kernel
+	 * size eventfd_signal() also, adds to the "count" counter and
+	 * issue a wakeup.
+	 */
+	__u64 count;
+};
+
+/*
+ * Adds "n" to the eventfd counter "count". Returns "n" in case of
+ * success, or a value lower then "n" in case of coutner overflow.
+ * This function is supposed to be called by the kernel in paths
+ * that do not allow sleeping. In this function we allow the counter
+ * to reach the ULLONG_MAX value, and we signal this as overflow
+ * condition by returining a POLLERR to poll(2).
+ */
+int eventfd_signal(struct file *file, int n)
+{
+	struct eventfd_ctx *ctx = file->private_data;
+	unsigned long flags;
+
+	if (n < 0)
+		return -EINVAL;
+	spin_lock_irqsave(&ctx->lock, flags);
+	if (ULLONG_MAX - ctx->count < n)
+		n = (int) (ULLONG_MAX - ctx->count);
+	ctx->count += n;
+	if (waitqueue_active(&ctx->wqh))
+		wake_up_locked(&ctx->wqh);
+	spin_unlock_irqrestore(&ctx->lock, flags);
+
+	return n;
+}
+
+static int eventfd_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
+static unsigned int eventfd_poll(struct file *file, poll_table *wait)
+{
+	struct eventfd_ctx *ctx = file->private_data;
+	unsigned int events = 0;
+	unsigned long flags;
+
+	poll_wait(file, &ctx->wqh, wait);
+
+	spin_lock_irqsave(&ctx->lock, flags);
+	if (ctx->count > 0)
+		events |= POLLIN;
+	if (ctx->count == ULLONG_MAX)
+		events |= POLLERR;
+	if (ULLONG_MAX - 1 > ctx->count)
+		events |= POLLOUT;
+	spin_unlock_irqrestore(&ctx->lock, flags);
+
+	return events;
+}
+
+static ssize_t eventfd_read(struct file *file, char __user *buf, size_t count,
+			    loff_t *ppos)
+{
+	struct eventfd_ctx *ctx = file->private_data;
+	ssize_t res;
+	__u64 ucnt;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (count < sizeof(ucnt))
+		return -EINVAL;
+	spin_lock_irq(&ctx->lock);
+	res = -EAGAIN;
+	ucnt = ctx->count;
+	if (ucnt > 0)
+		res = sizeof(ucnt);
+	else if (!(file->f_flags & O_NONBLOCK)) {
+		__add_wait_queue(&ctx->wqh, &wait);
+		for (res = 0;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (ctx->count > 0) {
+				ucnt = ctx->count;
+				res = sizeof(ucnt);
+				break;
+			}
+			if (signal_pending(current)) {
+				res = -ERESTARTSYS;
+				break;
+			}
+			spin_unlock_irq(&ctx->lock);
+			schedule();
+			spin_lock_irq(&ctx->lock);
+		}
+		__remove_wait_queue(&ctx->wqh, &wait);
+		__set_current_state(TASK_RUNNING);
+	}
+	if (res > 0) {
+		ctx->count = 0;
+		if (waitqueue_active(&ctx->wqh))
+			wake_up_locked(&ctx->wqh);
+	}
+	spin_unlock_irq(&ctx->lock);
+	if (res > 0 && put_user(ucnt, (__u64 __user *) buf))
+		return -EFAULT;
+
+	return res;
+}
+
+static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t count,
+			     loff_t *ppos)
+{
+	struct eventfd_ctx *ctx = file->private_data;
+	ssize_t res;
+	__u64 ucnt;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (count < sizeof(ucnt))
+		return -EINVAL;
+	if (copy_from_user(&ucnt, buf, sizeof(ucnt)))
+		return -EFAULT;
+	if (ucnt == ULLONG_MAX)
+		return -EINVAL;
+	spin_lock_irq(&ctx->lock);
+	res = -EAGAIN;
+	if (ULLONG_MAX - ctx->count > ucnt)
+		res = sizeof(ucnt);
+	else if (!(file->f_flags & O_NONBLOCK)) {
+		__add_wait_queue(&ctx->wqh, &wait);
+		for (res = 0;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (ULLONG_MAX - ctx->count > ucnt) {
+				res = sizeof(ucnt);
+				break;
+			}
+			if (signal_pending(current)) {
+				res = -ERESTARTSYS;
+				break;
+			}
+			spin_unlock_irq(&ctx->lock);
+			schedule();
+			spin_lock_irq(&ctx->lock);
+		}
+		__remove_wait_queue(&ctx->wqh, &wait);
+		__set_current_state(TASK_RUNNING);
+	}
+	if (res > 0) {
+		ctx->count += ucnt;
+		if (waitqueue_active(&ctx->wqh))
+			wake_up_locked(&ctx->wqh);
+	}
+	spin_unlock_irq(&ctx->lock);
+
+	return res;
+}
+
+static const struct file_operations eventfd_fops = {
+	.release	= eventfd_release,
+	.poll		= eventfd_poll,
+	.read		= eventfd_read,
+	.write		= eventfd_write,
+};
+
+struct file *eventfd_fget(int fd)
+{
+	struct file *file;
+
+	file = fget(fd);
+	if (!file)
+		return ERR_PTR(-EBADF);
+	if (file->f_op != &eventfd_fops) {
+		fput(file);
+		return ERR_PTR(-EINVAL);
+	}
+
+	return file;
+}
+
+asmlinkage long sys_eventfd(unsigned int count)
+{
+	int error, fd;
+	struct eventfd_ctx *ctx;
+	struct file *file;
+	struct inode *inode;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	init_waitqueue_head(&ctx->wqh);
+	spin_lock_init(&ctx->lock);
+	ctx->count = count;
+
+	/*
+	 * When we call this, the initialization must be complete, since
+	 * anon_inode_getfd() will install the fd.
+	 */
+	error = anon_inode_getfd(&fd, &inode, &file, "[eventfd]",
+				 &eventfd_fops, ctx);
+	if (!error)
+		return fd;
+
+	kfree(ctx);
+	return error;
+}
+
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index b5c7ca5..1aad34e 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -11,7 +11,6 @@
  *
  */
 
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -34,6 +33,7 @@
 #include <linux/mount.h>
 #include <linux/bitops.h>
 #include <linux/mutex.h>
+#include <linux/anon_inodes.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -41,7 +41,6 @@
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 
-
 /*
  * LOCKING:
  * There are three level of locking required by epoll :
@@ -74,9 +73,6 @@
  * a greater scalability.
  */
 
-
-#define EVENTPOLLFS_MAGIC 0x03111965 /* My birthday should work for this :) */
-
 #define DEBUG_EPOLL 0
 
 #if DEBUG_EPOLL > 0
@@ -106,7 +102,6 @@
 
 #define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
 
-
 struct epoll_filefd {
 	struct file *file;
 	int fd;
@@ -224,43 +219,6 @@
 	struct epitem *epi;
 };
 
-
-
-static void ep_poll_safewake_init(struct poll_safewake *psw);
-static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
-		    struct eventpoll *ep);
-static int ep_alloc(struct eventpoll **pep);
-static void ep_free(struct eventpoll *ep);
-static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
-static void ep_use_epitem(struct epitem *epi);
-static void ep_release_epitem(struct epitem *epi);
-static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
-				 poll_table *pt);
-static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi);
-static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
-		     struct file *tfile, int fd);
-static int ep_modify(struct eventpoll *ep, struct epitem *epi,
-		     struct epoll_event *event);
-static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi);
-static int ep_unlink(struct eventpoll *ep, struct epitem *epi);
-static int ep_remove(struct eventpoll *ep, struct epitem *epi);
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key);
-static int ep_eventpoll_close(struct inode *inode, struct file *file);
-static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait);
-static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
-			  struct epoll_event __user *events, int maxevents);
-static int ep_events_transfer(struct eventpoll *ep,
-			      struct epoll_event __user *events,
-			      int maxevents);
-static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
-		   int maxevents, long timeout);
-static int eventpollfs_delete_dentry(struct dentry *dentry);
-static struct inode *ep_eventpoll_inode(void);
-static int eventpollfs_get_sb(struct file_system_type *fs_type,
-			      int flags, const char *dev_name,
-			      void *data, struct vfsmount *mnt);
-
 /*
  * This semaphore is used to serialize ep_free() and eventpoll_release_file().
  */
@@ -275,37 +233,6 @@
 /* Slab cache used to allocate "struct eppoll_entry" */
 static struct kmem_cache *pwq_cache __read_mostly;
 
-/* Virtual fs used to allocate inodes for eventpoll files */
-static struct vfsmount *eventpoll_mnt __read_mostly;
-
-/* File callbacks that implement the eventpoll file behaviour */
-static const struct file_operations eventpoll_fops = {
-	.release	= ep_eventpoll_close,
-	.poll		= ep_eventpoll_poll
-};
-
-/*
- * This is used to register the virtual file system from where
- * eventpoll inodes are allocated.
- */
-static struct file_system_type eventpoll_fs_type = {
-	.name		= "eventpollfs",
-	.get_sb		= eventpollfs_get_sb,
-	.kill_sb	= kill_anon_super,
-};
-
-/* Very basic directory entry operations for the eventpoll virtual file system */
-static struct dentry_operations eventpollfs_dentry_operations = {
-	.d_delete	= eventpollfs_delete_dentry,
-};
-
-
-
-/* Fast test to see if the file is an evenpoll file */
-static inline int is_file_epoll(struct file *f)
-{
-	return f->f_op == &eventpoll_fops;
-}
 
 /* Setup the structure that is used as key for the rb-tree */
 static inline void ep_set_ffd(struct epoll_filefd *ffd,
@@ -374,7 +301,6 @@
 	spin_lock_init(&psw->lock);
 }
 
-
 /*
  * Perform a safe wake up of the poll wait list. The problem is that
  * with the new callback'd wake up system, it is possible that the
@@ -429,400 +355,145 @@
 	spin_unlock_irqrestore(&psw->lock, flags);
 }
 
+/*
+ * This function unregister poll callbacks from the associated file descriptor.
+ * Since this must be called without holding "ep->lock" the atomic exchange trick
+ * will protect us from multiple unregister.
+ */
+static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
+{
+	int nwait;
+	struct list_head *lsthead = &epi->pwqlist;
+	struct eppoll_entry *pwq;
+
+	/* This is called without locks, so we need the atomic exchange */
+	nwait = xchg(&epi->nwait, 0);
+
+	if (nwait) {
+		while (!list_empty(lsthead)) {
+			pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
+
+			list_del_init(&pwq->llink);
+			remove_wait_queue(pwq->whead, &pwq->wait);
+			kmem_cache_free(pwq_cache, pwq);
+		}
+	}
+}
 
 /*
- * This is called from eventpoll_release() to unlink files from the eventpoll
- * interface. We need to have this facility to cleanup correctly files that are
- * closed without being removed from the eventpoll interface.
+ * Unlink the "struct epitem" from all places it might have been hooked up.
+ * This function must be called with write IRQ lock on "ep->lock".
  */
-void eventpoll_release_file(struct file *file)
+static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
 {
-	struct list_head *lsthead = &file->f_ep_links;
-	struct eventpoll *ep;
-	struct epitem *epi;
+	int error;
 
 	/*
-	 * We don't want to get "file->f_ep_lock" because it is not
-	 * necessary. It is not necessary because we're in the "struct file"
-	 * cleanup path, and this means that noone is using this file anymore.
-	 * The only hit might come from ep_free() but by holding the semaphore
-	 * will correctly serialize the operation. We do need to acquire
-	 * "ep->sem" after "epmutex" because ep_remove() requires it when called
-	 * from anywhere but ep_free().
+	 * It can happen that this one is called for an item already unlinked.
+	 * The check protect us from doing a double unlink ( crash ).
 	 */
-	mutex_lock(&epmutex);
+	error = -ENOENT;
+	if (!ep_rb_linked(&epi->rbn))
+		goto error_return;
 
-	while (!list_empty(lsthead)) {
-		epi = list_first_entry(lsthead, struct epitem, fllink);
+	/*
+	 * Clear the event mask for the unlinked item. This will avoid item
+	 * notifications to be sent after the unlink operation from inside
+	 * the kernel->userspace event transfer loop.
+	 */
+	epi->event.events = 0;
 
-		ep = epi->ep;
+	/*
+	 * At this point is safe to do the job, unlink the item from our rb-tree.
+	 * This operation togheter with the above check closes the door to
+	 * double unlinks.
+	 */
+	ep_rb_erase(&epi->rbn, &ep->rbr);
+
+	/*
+	 * If the item we are going to remove is inside the ready file descriptors
+	 * we want to remove it from this list to avoid stale events.
+	 */
+	if (ep_is_linked(&epi->rdllink))
+		list_del_init(&epi->rdllink);
+
+	error = 0;
+error_return:
+
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n",
+		     current, ep, epi->ffd.file, error));
+
+	return error;
+}
+
+/*
+ * Increment the usage count of the "struct epitem" making it sure
+ * that the user will have a valid pointer to reference.
+ */
+static void ep_use_epitem(struct epitem *epi)
+{
+	atomic_inc(&epi->usecnt);
+}
+
+/*
+ * Decrement ( release ) the usage count by signaling that the user
+ * has finished using the structure. It might lead to freeing the
+ * structure itself if the count goes to zero.
+ */
+static void ep_release_epitem(struct epitem *epi)
+{
+	if (atomic_dec_and_test(&epi->usecnt))
+		kmem_cache_free(epi_cache, epi);
+}
+
+/*
+ * Removes a "struct epitem" from the eventpoll RB tree and deallocates
+ * all the associated resources.
+ */
+static int ep_remove(struct eventpoll *ep, struct epitem *epi)
+{
+	int error;
+	unsigned long flags;
+	struct file *file = epi->ffd.file;
+
+	/*
+	 * Removes poll wait queue hooks. We _have_ to do this without holding
+	 * the "ep->lock" otherwise a deadlock might occur. This because of the
+	 * sequence of the lock acquisition. Here we do "ep->lock" then the wait
+	 * queue head lock when unregistering the wait queue. The wakeup callback
+	 * will run by holding the wait queue head lock and will call our callback
+	 * that will try to get "ep->lock".
+	 */
+	ep_unregister_pollwait(ep, epi);
+
+	/* Remove the current item from the list of epoll hooks */
+	spin_lock(&file->f_ep_lock);
+	if (ep_is_linked(&epi->fllink))
 		list_del_init(&epi->fllink);
-		down_write(&ep->sem);
-		ep_remove(ep, epi);
-		up_write(&ep->sem);
-	}
+	spin_unlock(&file->f_ep_lock);
 
-	mutex_unlock(&epmutex);
-}
+	/* We need to acquire the write IRQ lock before calling ep_unlink() */
+	write_lock_irqsave(&ep->lock, flags);
 
+	/* Really unlink the item from the RB tree */
+	error = ep_unlink(ep, epi);
 
-/*
- * It opens an eventpoll file descriptor by suggesting a storage of "size"
- * file descriptors. The size parameter is just an hint about how to size
- * data structures. It won't prevent the user to store more than "size"
- * file descriptors inside the epoll interface. It is the kernel part of
- * the userspace epoll_create(2).
- */
-asmlinkage long sys_epoll_create(int size)
-{
-	int error, fd = -1;
-	struct eventpoll *ep;
-	struct inode *inode;
-	struct file *file;
+	write_unlock_irqrestore(&ep->lock, flags);
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
-		     current, size));
-
-	/*
-	 * Sanity check on the size parameter, and create the internal data
-	 * structure ( "struct eventpoll" ).
-	 */
-	error = -EINVAL;
-	if (size <= 0 || (error = ep_alloc(&ep)) != 0)
-		goto eexit_1;
-
-	/*
-	 * Creates all the items needed to setup an eventpoll file. That is,
-	 * a file structure, and inode and a free file descriptor.
-	 */
-	error = ep_getfd(&fd, &inode, &file, ep);
 	if (error)
-		goto eexit_2;
+		goto error_return;
 
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
-		     current, size, fd));
+	/* At this point it is safe to free the eventpoll item */
+	ep_release_epitem(epi);
 
-	return fd;
-
-eexit_2:
-	ep_free(ep);
-	kfree(ep);
-eexit_1:
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
-		     current, size, error));
-	return error;
-}
-
-
-/*
- * The following function implements the controller interface for
- * the eventpoll file that enables the insertion/removal/change of
- * file descriptors inside the interest set.  It represents
- * the kernel part of the user space epoll_ctl(2).
- */
-asmlinkage long
-sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
-{
-	int error;
-	struct file *file, *tfile;
-	struct eventpoll *ep;
-	struct epitem *epi;
-	struct epoll_event epds;
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n",
-		     current, epfd, op, fd, event));
-
-	error = -EFAULT;
-	if (ep_op_has_event(op) &&
-	    copy_from_user(&epds, event, sizeof(struct epoll_event)))
-		goto eexit_1;
-
-	/* Get the "struct file *" for the eventpoll file */
-	error = -EBADF;
-	file = fget(epfd);
-	if (!file)
-		goto eexit_1;
-
-	/* Get the "struct file *" for the target file */
-	tfile = fget(fd);
-	if (!tfile)
-		goto eexit_2;
-
-	/* The target file descriptor must support poll */
-	error = -EPERM;
-	if (!tfile->f_op || !tfile->f_op->poll)
-		goto eexit_3;
-
-	/*
-	 * We have to check that the file structure underneath the file descriptor
-	 * the user passed to us _is_ an eventpoll file. And also we do not permit
-	 * adding an epoll file descriptor inside itself.
-	 */
-	error = -EINVAL;
-	if (file == tfile || !is_file_epoll(file))
-		goto eexit_3;
-
-	/*
-	 * At this point it is safe to assume that the "private_data" contains
-	 * our own data structure.
-	 */
-	ep = file->private_data;
-
-	down_write(&ep->sem);
-
-	/* Try to lookup the file inside our RB tree */
-	epi = ep_find(ep, tfile, fd);
-
-	error = -EINVAL;
-	switch (op) {
-	case EPOLL_CTL_ADD:
-		if (!epi) {
-			epds.events |= POLLERR | POLLHUP;
-
-			error = ep_insert(ep, &epds, tfile, fd);
-		} else
-			error = -EEXIST;
-		break;
-	case EPOLL_CTL_DEL:
-		if (epi)
-			error = ep_remove(ep, epi);
-		else
-			error = -ENOENT;
-		break;
-	case EPOLL_CTL_MOD:
-		if (epi) {
-			epds.events |= POLLERR | POLLHUP;
-			error = ep_modify(ep, epi, &epds);
-		} else
-			error = -ENOENT;
-		break;
-	}
-
-	/*
-	 * The function ep_find() increments the usage count of the structure
-	 * so, if this is not NULL, we need to release it.
-	 */
-	if (epi)
-		ep_release_epitem(epi);
-
-	up_write(&ep->sem);
-
-eexit_3:
-	fput(tfile);
-eexit_2:
-	fput(file);
-eexit_1:
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n",
-		     current, epfd, op, fd, event, error));
+	error = 0;
+error_return:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n",
+		     current, ep, file, error));
 
 	return error;
 }
 
-
-/*
- * Implement the event wait interface for the eventpoll file. It is the kernel
- * part of the user space epoll_wait(2).
- */
-asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
-			       int maxevents, int timeout)
-{
-	int error;
-	struct file *file;
-	struct eventpoll *ep;
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n",
-		     current, epfd, events, maxevents, timeout));
-
-	/* The maximum number of event must be greater than zero */
-	if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
-		return -EINVAL;
-
-	/* Verify that the area passed by the user is writeable */
-	if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) {
-		error = -EFAULT;
-		goto eexit_1;
-	}
-
-	/* Get the "struct file *" for the eventpoll file */
-	error = -EBADF;
-	file = fget(epfd);
-	if (!file)
-		goto eexit_1;
-
-	/*
-	 * We have to check that the file structure underneath the fd
-	 * the user passed to us _is_ an eventpoll file.
-	 */
-	error = -EINVAL;
-	if (!is_file_epoll(file))
-		goto eexit_2;
-
-	/*
-	 * At this point it is safe to assume that the "private_data" contains
-	 * our own data structure.
-	 */
-	ep = file->private_data;
-
-	/* Time to fish for events ... */
-	error = ep_poll(ep, events, maxevents, timeout);
-
-eexit_2:
-	fput(file);
-eexit_1:
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n",
-		     current, epfd, events, maxevents, timeout, error));
-
-	return error;
-}
-
-
-#ifdef TIF_RESTORE_SIGMASK
-
-/*
- * Implement the event wait interface for the eventpoll file. It is the kernel
- * part of the user space epoll_pwait(2).
- */
-asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
-		int maxevents, int timeout, const sigset_t __user *sigmask,
-		size_t sigsetsize)
-{
-	int error;
-	sigset_t ksigmask, sigsaved;
-
-	/*
-	 * If the caller wants a certain signal mask to be set during the wait,
-	 * we apply it here.
-	 */
-	if (sigmask) {
-		if (sigsetsize != sizeof(sigset_t))
-			return -EINVAL;
-		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
-			return -EFAULT;
-		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
-		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
-	}
-
-	error = sys_epoll_wait(epfd, events, maxevents, timeout);
-
-	/*
-	 * If we changed the signal mask, we need to restore the original one.
-	 * In case we've got a signal while waiting, we do not restore the
-	 * signal mask yet, and we allow do_signal() to deliver the signal on
-	 * the way back to userspace, before the signal mask is restored.
-	 */
-	if (sigmask) {
-		if (error == -EINTR) {
-			memcpy(&current->saved_sigmask, &sigsaved,
-				sizeof(sigsaved));
-			set_thread_flag(TIF_RESTORE_SIGMASK);
-		} else
-			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
-	}
-
-	return error;
-}
-
-#endif /* #ifdef TIF_RESTORE_SIGMASK */
-
-
-/*
- * Creates the file descriptor to be used by the epoll interface.
- */
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
-		    struct eventpoll *ep)
-{
-	struct qstr this;
-	char name[32];
-	struct dentry *dentry;
-	struct inode *inode;
-	struct file *file;
-	int error, fd;
-
-	/* Get an ready to use file */
-	error = -ENFILE;
-	file = get_empty_filp();
-	if (!file)
-		goto eexit_1;
-
-	/* Allocates an inode from the eventpoll file system */
-	inode = ep_eventpoll_inode();
-	if (IS_ERR(inode)) {
-		error = PTR_ERR(inode);
-		goto eexit_2;
-	}
-
-	/* Allocates a free descriptor to plug the file onto */
-	error = get_unused_fd();
-	if (error < 0)
-		goto eexit_3;
-	fd = error;
-
-	/*
-	 * Link the inode to a directory entry by creating a unique name
-	 * using the inode number.
-	 */
-	error = -ENOMEM;
-	sprintf(name, "[%lu]", inode->i_ino);
-	this.name = name;
-	this.len = strlen(name);
-	this.hash = inode->i_ino;
-	dentry = d_alloc(eventpoll_mnt->mnt_sb->s_root, &this);
-	if (!dentry)
-		goto eexit_4;
-	dentry->d_op = &eventpollfs_dentry_operations;
-	d_add(dentry, inode);
-	file->f_path.mnt = mntget(eventpoll_mnt);
-	file->f_path.dentry = dentry;
-	file->f_mapping = inode->i_mapping;
-
-	file->f_pos = 0;
-	file->f_flags = O_RDONLY;
-	file->f_op = &eventpoll_fops;
-	file->f_mode = FMODE_READ;
-	file->f_version = 0;
-	file->private_data = ep;
-
-	/* Install the new setup file into the allocated fd. */
-	fd_install(fd, file);
-
-	*efd = fd;
-	*einode = inode;
-	*efile = file;
-	return 0;
-
-eexit_4:
-	put_unused_fd(fd);
-eexit_3:
-	iput(inode);
-eexit_2:
-	put_filp(file);
-eexit_1:
-	return error;
-}
-
-
-static int ep_alloc(struct eventpoll **pep)
-{
-	struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
-
-	if (!ep)
-		return -ENOMEM;
-
-	rwlock_init(&ep->lock);
-	init_rwsem(&ep->sem);
-	init_waitqueue_head(&ep->wq);
-	init_waitqueue_head(&ep->poll_wait);
-	INIT_LIST_HEAD(&ep->rdllist);
-	ep->rbr = RB_ROOT;
-
-	*pep = ep;
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
-		     current, ep));
-	return 0;
-}
-
-
 static void ep_free(struct eventpoll *ep)
 {
 	struct rb_node *rbp;
@@ -865,6 +536,104 @@
 	mutex_unlock(&epmutex);
 }
 
+static int ep_eventpoll_release(struct inode *inode, struct file *file)
+{
+	struct eventpoll *ep = file->private_data;
+
+	if (ep) {
+		ep_free(ep);
+		kfree(ep);
+	}
+
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep));
+	return 0;
+}
+
+static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
+{
+	unsigned int pollflags = 0;
+	unsigned long flags;
+	struct eventpoll *ep = file->private_data;
+
+	/* Insert inside our poll wait queue */
+	poll_wait(file, &ep->poll_wait, wait);
+
+	/* Check our condition */
+	read_lock_irqsave(&ep->lock, flags);
+	if (!list_empty(&ep->rdllist))
+		pollflags = POLLIN | POLLRDNORM;
+	read_unlock_irqrestore(&ep->lock, flags);
+
+	return pollflags;
+}
+
+/* File callbacks that implement the eventpoll file behaviour */
+static const struct file_operations eventpoll_fops = {
+	.release	= ep_eventpoll_release,
+	.poll		= ep_eventpoll_poll
+};
+
+/* Fast test to see if the file is an evenpoll file */
+static inline int is_file_epoll(struct file *f)
+{
+	return f->f_op == &eventpoll_fops;
+}
+
+/*
+ * This is called from eventpoll_release() to unlink files from the eventpoll
+ * interface. We need to have this facility to cleanup correctly files that are
+ * closed without being removed from the eventpoll interface.
+ */
+void eventpoll_release_file(struct file *file)
+{
+	struct list_head *lsthead = &file->f_ep_links;
+	struct eventpoll *ep;
+	struct epitem *epi;
+
+	/*
+	 * We don't want to get "file->f_ep_lock" because it is not
+	 * necessary. It is not necessary because we're in the "struct file"
+	 * cleanup path, and this means that noone is using this file anymore.
+	 * The only hit might come from ep_free() but by holding the semaphore
+	 * will correctly serialize the operation. We do need to acquire
+	 * "ep->sem" after "epmutex" because ep_remove() requires it when called
+	 * from anywhere but ep_free().
+	 */
+	mutex_lock(&epmutex);
+
+	while (!list_empty(lsthead)) {
+		epi = list_first_entry(lsthead, struct epitem, fllink);
+
+		ep = epi->ep;
+		list_del_init(&epi->fllink);
+		down_write(&ep->sem);
+		ep_remove(ep, epi);
+		up_write(&ep->sem);
+	}
+
+	mutex_unlock(&epmutex);
+}
+
+static int ep_alloc(struct eventpoll **pep)
+{
+	struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL);
+
+	if (!ep)
+		return -ENOMEM;
+
+	rwlock_init(&ep->lock);
+	init_rwsem(&ep->sem);
+	init_waitqueue_head(&ep->wq);
+	init_waitqueue_head(&ep->poll_wait);
+	INIT_LIST_HEAD(&ep->rdllist);
+	ep->rbr = RB_ROOT;
+
+	*pep = ep;
+
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_alloc() ep=%p\n",
+		     current, ep));
+	return 0;
+}
 
 /*
  * Search the file inside the eventpoll tree. It add usage count to
@@ -902,31 +671,59 @@
 	return epir;
 }
 
-
 /*
- * Increment the usage count of the "struct epitem" making it sure
- * that the user will have a valid pointer to reference.
+ * This is the callback that is passed to the wait queue wakeup
+ * machanism. It is called by the stored file descriptors when they
+ * have events to report.
  */
-static void ep_use_epitem(struct epitem *epi)
+static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
 {
+	int pwake = 0;
+	unsigned long flags;
+	struct epitem *epi = ep_item_from_wait(wait);
+	struct eventpoll *ep = epi->ep;
 
-	atomic_inc(&epi->usecnt);
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
+		     current, epi->ffd.file, epi, ep));
+
+	write_lock_irqsave(&ep->lock, flags);
+
+	/*
+	 * If the event mask does not contain any poll(2) event, we consider the
+	 * descriptor to be disabled. This condition is likely the effect of the
+	 * EPOLLONESHOT bit that disables the descriptor when an event is received,
+	 * until the next EPOLL_CTL_MOD will be issued.
+	 */
+	if (!(epi->event.events & ~EP_PRIVATE_BITS))
+		goto is_disabled;
+
+	/* If this file is already in the ready list we exit soon */
+	if (ep_is_linked(&epi->rdllink))
+		goto is_linked;
+
+	list_add_tail(&epi->rdllink, &ep->rdllist);
+
+is_linked:
+	/*
+	 * Wake up ( if active ) both the eventpoll wait list and the ->poll()
+	 * wait list.
+	 */
+	if (waitqueue_active(&ep->wq))
+		__wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+				 TASK_INTERRUPTIBLE);
+	if (waitqueue_active(&ep->poll_wait))
+		pwake++;
+
+is_disabled:
+	write_unlock_irqrestore(&ep->lock, flags);
+
+	/* We have to call this outside the lock */
+	if (pwake)
+		ep_poll_safewake(&psw, &ep->poll_wait);
+
+	return 1;
 }
 
-
-/*
- * Decrement ( release ) the usage count by signaling that the user
- * has finished using the structure. It might lead to freeing the
- * structure itself if the count goes to zero.
- */
-static void ep_release_epitem(struct epitem *epi)
-{
-
-	if (atomic_dec_and_test(&epi->usecnt))
-		kmem_cache_free(epi_cache, epi);
-}
-
-
 /*
  * This is the callback that is used to add our wait queue to the
  * target file wakeup lists.
@@ -950,7 +747,6 @@
 	}
 }
 
-
 static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
 {
 	int kcmp;
@@ -970,7 +766,6 @@
 	rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
-
 static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 		     struct file *tfile, int fd)
 {
@@ -981,7 +776,7 @@
 
 	error = -ENOMEM;
 	if (!(epi = kmem_cache_alloc(epi_cache, GFP_KERNEL)))
-		goto eexit_1;
+		goto error_return;
 
 	/* Item initialization follow here ... */
 	ep_rb_initnode(&epi->rbn);
@@ -1011,7 +806,7 @@
 	 * high memory pressure.
 	 */
 	if (epi->nwait < 0)
-		goto eexit_2;
+		goto error_unregister;
 
 	/* Add the current item to the list of active epoll hook for this file */
 	spin_lock(&tfile->f_ep_lock);
@@ -1046,7 +841,7 @@
 
 	return 0;
 
-eexit_2:
+error_unregister:
 	ep_unregister_pollwait(ep, epi);
 
 	/*
@@ -1059,11 +854,10 @@
 	write_unlock_irqrestore(&ep->lock, flags);
 
 	kmem_cache_free(epi_cache, epi);
-eexit_1:
+error_return:
 	return error;
 }
 
-
 /*
  * Modify the interest event mask by dropping an event if the new mask
  * has a match in the current file status.
@@ -1126,216 +920,6 @@
 	return 0;
 }
 
-
-/*
- * This function unregister poll callbacks from the associated file descriptor.
- * Since this must be called without holding "ep->lock" the atomic exchange trick
- * will protect us from multiple unregister.
- */
-static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
-{
-	int nwait;
-	struct list_head *lsthead = &epi->pwqlist;
-	struct eppoll_entry *pwq;
-
-	/* This is called without locks, so we need the atomic exchange */
-	nwait = xchg(&epi->nwait, 0);
-
-	if (nwait) {
-		while (!list_empty(lsthead)) {
-			pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
-
-			list_del_init(&pwq->llink);
-			remove_wait_queue(pwq->whead, &pwq->wait);
-			kmem_cache_free(pwq_cache, pwq);
-		}
-	}
-}
-
-
-/*
- * Unlink the "struct epitem" from all places it might have been hooked up.
- * This function must be called with write IRQ lock on "ep->lock".
- */
-static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
-{
-	int error;
-
-	/*
-	 * It can happen that this one is called for an item already unlinked.
-	 * The check protect us from doing a double unlink ( crash ).
-	 */
-	error = -ENOENT;
-	if (!ep_rb_linked(&epi->rbn))
-		goto eexit_1;
-
-	/*
-	 * Clear the event mask for the unlinked item. This will avoid item
-	 * notifications to be sent after the unlink operation from inside
-	 * the kernel->userspace event transfer loop.
-	 */
-	epi->event.events = 0;
-
-	/*
-	 * At this point is safe to do the job, unlink the item from our rb-tree.
-	 * This operation togheter with the above check closes the door to
-	 * double unlinks.
-	 */
-	ep_rb_erase(&epi->rbn, &ep->rbr);
-
-	/*
-	 * If the item we are going to remove is inside the ready file descriptors
-	 * we want to remove it from this list to avoid stale events.
-	 */
-	if (ep_is_linked(&epi->rdllink))
-		list_del_init(&epi->rdllink);
-
-	error = 0;
-eexit_1:
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_unlink(%p, %p) = %d\n",
-		     current, ep, epi->ffd.file, error));
-
-	return error;
-}
-
-
-/*
- * Removes a "struct epitem" from the eventpoll RB tree and deallocates
- * all the associated resources.
- */
-static int ep_remove(struct eventpoll *ep, struct epitem *epi)
-{
-	int error;
-	unsigned long flags;
-	struct file *file = epi->ffd.file;
-
-	/*
-	 * Removes poll wait queue hooks. We _have_ to do this without holding
-	 * the "ep->lock" otherwise a deadlock might occur. This because of the
-	 * sequence of the lock acquisition. Here we do "ep->lock" then the wait
-	 * queue head lock when unregistering the wait queue. The wakeup callback
-	 * will run by holding the wait queue head lock and will call our callback
-	 * that will try to get "ep->lock".
-	 */
-	ep_unregister_pollwait(ep, epi);
-
-	/* Remove the current item from the list of epoll hooks */
-	spin_lock(&file->f_ep_lock);
-	if (ep_is_linked(&epi->fllink))
-		list_del_init(&epi->fllink);
-	spin_unlock(&file->f_ep_lock);
-
-	/* We need to acquire the write IRQ lock before calling ep_unlink() */
-	write_lock_irqsave(&ep->lock, flags);
-
-	/* Really unlink the item from the RB tree */
-	error = ep_unlink(ep, epi);
-
-	write_unlock_irqrestore(&ep->lock, flags);
-
-	if (error)
-		goto eexit_1;
-
-	/* At this point it is safe to free the eventpoll item */
-	ep_release_epitem(epi);
-
-	error = 0;
-eexit_1:
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_remove(%p, %p) = %d\n",
-		     current, ep, file, error));
-
-	return error;
-}
-
-
-/*
- * This is the callback that is passed to the wait queue wakeup
- * machanism. It is called by the stored file descriptors when they
- * have events to report.
- */
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
-	int pwake = 0;
-	unsigned long flags;
-	struct epitem *epi = ep_item_from_wait(wait);
-	struct eventpoll *ep = epi->ep;
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
-		     current, epi->ffd.file, epi, ep));
-
-	write_lock_irqsave(&ep->lock, flags);
-
-	/*
-	 * If the event mask does not contain any poll(2) event, we consider the
-	 * descriptor to be disabled. This condition is likely the effect of the
-	 * EPOLLONESHOT bit that disables the descriptor when an event is received,
-	 * until the next EPOLL_CTL_MOD will be issued.
-	 */
-	if (!(epi->event.events & ~EP_PRIVATE_BITS))
-		goto is_disabled;
-
-	/* If this file is already in the ready list we exit soon */
-	if (ep_is_linked(&epi->rdllink))
-		goto is_linked;
-
-	list_add_tail(&epi->rdllink, &ep->rdllist);
-
-is_linked:
-	/*
-	 * Wake up ( if active ) both the eventpoll wait list and the ->poll()
-	 * wait list.
-	 */
-	if (waitqueue_active(&ep->wq))
-		__wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
-				 TASK_INTERRUPTIBLE);
-	if (waitqueue_active(&ep->poll_wait))
-		pwake++;
-
-is_disabled:
-	write_unlock_irqrestore(&ep->lock, flags);
-
-	/* We have to call this outside the lock */
-	if (pwake)
-		ep_poll_safewake(&psw, &ep->poll_wait);
-
-	return 1;
-}
-
-
-static int ep_eventpoll_close(struct inode *inode, struct file *file)
-{
-	struct eventpoll *ep = file->private_data;
-
-	if (ep) {
-		ep_free(ep);
-		kfree(ep);
-	}
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: close() ep=%p\n", current, ep));
-	return 0;
-}
-
-
-static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait)
-{
-	unsigned int pollflags = 0;
-	unsigned long flags;
-	struct eventpoll *ep = file->private_data;
-
-	/* Insert inside our poll wait queue */
-	poll_wait(file, &ep->poll_wait, wait);
-
-	/* Check our condition */
-	read_lock_irqsave(&ep->lock, flags);
-	if (!list_empty(&ep->rdllist))
-		pollflags = POLLIN | POLLRDNORM;
-	read_unlock_irqrestore(&ep->lock, flags);
-
-	return pollflags;
-}
-
-
 /*
  * This function is called without holding the "ep->lock" since the call to
  * __copy_to_user() might sleep, and also f_op->poll() might reenable the IRQ
@@ -1447,7 +1031,6 @@
 	return eventcnt == 0 ? error: eventcnt;
 }
 
-
 /*
  * Perform the transfer of events to user space.
  */
@@ -1483,7 +1066,6 @@
 	return eventcnt;
 }
 
-
 static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
 		   int maxevents, long timeout)
 {
@@ -1553,52 +1135,262 @@
 	return res;
 }
 
-static int eventpollfs_delete_dentry(struct dentry *dentry)
+/*
+ * It opens an eventpoll file descriptor by suggesting a storage of "size"
+ * file descriptors. The size parameter is just an hint about how to size
+ * data structures. It won't prevent the user to store more than "size"
+ * file descriptors inside the epoll interface. It is the kernel part of
+ * the userspace epoll_create(2).
+ */
+asmlinkage long sys_epoll_create(int size)
 {
+	int error, fd = -1;
+	struct eventpoll *ep;
+	struct inode *inode;
+	struct file *file;
 
-	return 1;
-}
-
-static struct inode *ep_eventpoll_inode(void)
-{
-	int error = -ENOMEM;
-	struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
-
-	if (!inode)
-		goto eexit_1;
-
-	inode->i_fop = &eventpoll_fops;
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
+		     current, size));
 
 	/*
-	 * Mark the inode dirty from the very beginning,
-	 * that way it will never be moved to the dirty
-	 * list because mark_inode_dirty() will think
-	 * that it already _is_ on the dirty list.
+	 * Sanity check on the size parameter, and create the internal data
+	 * structure ( "struct eventpoll" ).
 	 */
-	inode->i_state = I_DIRTY;
-	inode->i_mode = S_IRUSR | S_IWUSR;
-	inode->i_uid = current->fsuid;
-	inode->i_gid = current->fsgid;
-	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-	return inode;
+	error = -EINVAL;
+	if (size <= 0 || (error = ep_alloc(&ep)) != 0)
+		goto error_return;
 
-eexit_1:
-	return ERR_PTR(error);
+	/*
+	 * Creates all the items needed to setup an eventpoll file. That is,
+	 * a file structure, and inode and a free file descriptor.
+	 */
+	error = anon_inode_getfd(&fd, &inode, &file, "[eventpoll]",
+				 &eventpoll_fops, ep);
+	if (error)
+		goto error_free;
+
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
+		     current, size, fd));
+
+	return fd;
+
+error_free:
+	ep_free(ep);
+	kfree(ep);
+error_return:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d) = %d\n",
+		     current, size, error));
+	return error;
 }
 
-static int
-eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
-		   const char *dev_name, void *data, struct vfsmount *mnt)
+/*
+ * The following function implements the controller interface for
+ * the eventpoll file that enables the insertion/removal/change of
+ * file descriptors inside the interest set.  It represents
+ * the kernel part of the user space epoll_ctl(2).
+ */
+asmlinkage long sys_epoll_ctl(int epfd, int op, int fd,
+			      struct epoll_event __user *event)
 {
-	return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC,
-			     mnt);
+	int error;
+	struct file *file, *tfile;
+	struct eventpoll *ep;
+	struct epitem *epi;
+	struct epoll_event epds;
+
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p)\n",
+		     current, epfd, op, fd, event));
+
+	error = -EFAULT;
+	if (ep_op_has_event(op) &&
+	    copy_from_user(&epds, event, sizeof(struct epoll_event)))
+		goto error_return;
+
+	/* Get the "struct file *" for the eventpoll file */
+	error = -EBADF;
+	file = fget(epfd);
+	if (!file)
+		goto error_return;
+
+	/* Get the "struct file *" for the target file */
+	tfile = fget(fd);
+	if (!tfile)
+		goto error_fput;
+
+	/* The target file descriptor must support poll */
+	error = -EPERM;
+	if (!tfile->f_op || !tfile->f_op->poll)
+		goto error_tgt_fput;
+
+	/*
+	 * We have to check that the file structure underneath the file descriptor
+	 * the user passed to us _is_ an eventpoll file. And also we do not permit
+	 * adding an epoll file descriptor inside itself.
+	 */
+	error = -EINVAL;
+	if (file == tfile || !is_file_epoll(file))
+		goto error_tgt_fput;
+
+	/*
+	 * At this point it is safe to assume that the "private_data" contains
+	 * our own data structure.
+	 */
+	ep = file->private_data;
+
+	down_write(&ep->sem);
+
+	/* Try to lookup the file inside our RB tree */
+	epi = ep_find(ep, tfile, fd);
+
+	error = -EINVAL;
+	switch (op) {
+	case EPOLL_CTL_ADD:
+		if (!epi) {
+			epds.events |= POLLERR | POLLHUP;
+
+			error = ep_insert(ep, &epds, tfile, fd);
+		} else
+			error = -EEXIST;
+		break;
+	case EPOLL_CTL_DEL:
+		if (epi)
+			error = ep_remove(ep, epi);
+		else
+			error = -ENOENT;
+		break;
+	case EPOLL_CTL_MOD:
+		if (epi) {
+			epds.events |= POLLERR | POLLHUP;
+			error = ep_modify(ep, epi, &epds);
+		} else
+			error = -ENOENT;
+		break;
+	}
+	/*
+	 * The function ep_find() increments the usage count of the structure
+	 * so, if this is not NULL, we need to release it.
+	 */
+	if (epi)
+		ep_release_epitem(epi);
+	up_write(&ep->sem);
+
+error_tgt_fput:
+	fput(tfile);
+error_fput:
+	fput(file);
+error_return:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_ctl(%d, %d, %d, %p) = %d\n",
+		     current, epfd, op, fd, event, error));
+
+	return error;
 }
 
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_wait(2).
+ */
+asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
+			       int maxevents, int timeout)
+{
+	int error;
+	struct file *file;
+	struct eventpoll *ep;
+
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d)\n",
+		     current, epfd, events, maxevents, timeout));
+
+	/* The maximum number of event must be greater than zero */
+	if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
+		return -EINVAL;
+
+	/* Verify that the area passed by the user is writeable */
+	if (!access_ok(VERIFY_WRITE, events, maxevents * sizeof(struct epoll_event))) {
+		error = -EFAULT;
+		goto error_return;
+	}
+
+	/* Get the "struct file *" for the eventpoll file */
+	error = -EBADF;
+	file = fget(epfd);
+	if (!file)
+		goto error_return;
+
+	/*
+	 * We have to check that the file structure underneath the fd
+	 * the user passed to us _is_ an eventpoll file.
+	 */
+	error = -EINVAL;
+	if (!is_file_epoll(file))
+		goto error_fput;
+
+	/*
+	 * At this point it is safe to assume that the "private_data" contains
+	 * our own data structure.
+	 */
+	ep = file->private_data;
+
+	/* Time to fish for events ... */
+	error = ep_poll(ep, events, maxevents, timeout);
+
+error_fput:
+	fput(file);
+error_return:
+	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_wait(%d, %p, %d, %d) = %d\n",
+		     current, epfd, events, maxevents, timeout, error));
+
+	return error;
+}
+
+#ifdef TIF_RESTORE_SIGMASK
+
+/*
+ * Implement the event wait interface for the eventpoll file. It is the kernel
+ * part of the user space epoll_pwait(2).
+ */
+asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
+		int maxevents, int timeout, const sigset_t __user *sigmask,
+		size_t sigsetsize)
+{
+	int error;
+	sigset_t ksigmask, sigsaved;
+
+	/*
+	 * If the caller wants a certain signal mask to be set during the wait,
+	 * we apply it here.
+	 */
+	if (sigmask) {
+		if (sigsetsize != sizeof(sigset_t))
+			return -EINVAL;
+		if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
+			return -EFAULT;
+		sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+		sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
+	}
+
+	error = sys_epoll_wait(epfd, events, maxevents, timeout);
+
+	/*
+	 * If we changed the signal mask, we need to restore the original one.
+	 * In case we've got a signal while waiting, we do not restore the
+	 * signal mask yet, and we allow do_signal() to deliver the signal on
+	 * the way back to userspace, before the signal mask is restored.
+	 */
+	if (sigmask) {
+		if (error == -EINTR) {
+			memcpy(&current->saved_sigmask, &sigsaved,
+				sizeof(sigsaved));
+			set_thread_flag(TIF_RESTORE_SIGMASK);
+		} else
+			sigprocmask(SIG_SETMASK, &sigsaved, NULL);
+	}
+
+	return error;
+}
+
+#endif /* #ifdef TIF_RESTORE_SIGMASK */
 
 static int __init eventpoll_init(void)
 {
-	int error;
-
 	mutex_init(&epmutex);
 
 	/* Initialize the structure used to perform safe poll wait head wake ups */
@@ -1614,39 +1406,7 @@
 			sizeof(struct eppoll_entry), 0,
 			EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL);
 
-	/*
-	 * Register the virtual file system that will be the source of inodes
-	 * for the eventpoll files
-	 */
-	error = register_filesystem(&eventpoll_fs_type);
-	if (error)
-		goto epanic;
-
-	/* Mount the above commented virtual file system */
-	eventpoll_mnt = kern_mount(&eventpoll_fs_type);
-	error = PTR_ERR(eventpoll_mnt);
-	if (IS_ERR(eventpoll_mnt))
-		goto epanic;
-
-	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: successfully initialized.\n",
-			current));
 	return 0;
-
-epanic:
-	panic("eventpoll_init() failed\n");
 }
+fs_initcall(eventpoll_init);
 
-
-static void __exit eventpoll_exit(void)
-{
-	/* Undo all operations done inside eventpoll_init() */
-	unregister_filesystem(&eventpoll_fs_type);
-	mntput(eventpoll_mnt);
-	kmem_cache_destroy(pwq_cache);
-	kmem_cache_destroy(epi_cache);
-}
-
-module_init(eventpoll_init);
-module_exit(eventpoll_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/fs/exec.c b/fs/exec.c
index 1ba85c7..70fa365 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -50,6 +50,7 @@
 #include <linux/tsacct_kern.h>
 #include <linux/cn_proc.h>
 #include <linux/audit.h>
+#include <linux/signalfd.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -582,6 +583,13 @@
 	int count;
 
 	/*
+	 * Tell all the sighand listeners that this sighand has
+	 * been detached. The signalfd_detach() function grabs the
+	 * sighand lock, if signal listeners are present on the sighand.
+	 */
+	signalfd_detach(tsk);
+
+	/*
 	 * If we don't share sighandlers, then we aren't sharing anything
 	 * and we can just re-use it all.
 	 */
@@ -702,7 +710,7 @@
 		 */
 		detach_pid(tsk, PIDTYPE_PID);
 		tsk->pid = leader->pid;
-		attach_pid(tsk, PIDTYPE_PID,  tsk->pid);
+		attach_pid(tsk, PIDTYPE_PID,  find_pid(tsk->pid));
 		transfer_pid(leader, tsk, PIDTYPE_PGID);
 		transfer_pid(leader, tsk, PIDTYPE_SID);
 		list_replace_rcu(&leader->tasks, &tsk->tasks);
@@ -757,8 +765,7 @@
 		spin_unlock(&oldsighand->siglock);
 		write_unlock_irq(&tasklist_lock);
 
-		if (atomic_dec_and_test(&oldsighand->count))
-			kmem_cache_free(sighand_cachep, oldsighand);
+		__cleanup_sighand(oldsighand);
 	}
 
 	BUG_ON(!thread_group_leader(tsk));
@@ -1488,6 +1495,8 @@
 	int flag = 0;
 	int ispipe = 0;
 
+	audit_core_dumps(signr);
+
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
 		goto fail;
diff --git a/fs/locks.c b/fs/locks.c
index 671a034..8ec16ab 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -669,7 +669,6 @@
 {
 	struct file_lock *cfl;
 
-	fl->fl_type = F_UNLCK;
 	lock_kernel();
 	for (cfl = filp->f_path.dentry->d_inode->i_flock; cfl; cfl = cfl->fl_next) {
 		if (!IS_POSIX(cfl))
@@ -681,7 +680,8 @@
 		__locks_copy_lock(fl, cfl);
 		unlock_kernel();
 		return 1;
-	}
+	} else
+		fl->fl_type = F_UNLCK;
 	unlock_kernel();
 	return 0;
 }
@@ -1632,6 +1632,7 @@
 	flock->l_len = fl->fl_end == OFFSET_MAX ? 0 :
 		fl->fl_end - fl->fl_start + 1;
 	flock->l_whence = 0;
+	flock->l_type = fl->fl_type;
 	return 0;
 }
 
diff --git a/fs/mpage.c b/fs/mpage.c
index 0fb914f..c1698f2 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -454,11 +454,18 @@
  * written, so it can intelligently allocate a suitably-sized BIO.  For now,
  * just allocate full-size (16-page) BIOs.
  */
-static struct bio *
-__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
-	sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc,
-	writepage_t writepage_fn)
+struct mpage_data {
+	struct bio *bio;
+	sector_t last_block_in_bio;
+	get_block_t *get_block;
+	unsigned use_writepage;
+};
+
+static int __mpage_writepage(struct page *page, struct writeback_control *wbc,
+			     void *data)
 {
+	struct mpage_data *mpd = data;
+	struct bio *bio = mpd->bio;
 	struct address_space *mapping = page->mapping;
 	struct inode *inode = page->mapping->host;
 	const unsigned blkbits = inode->i_blkbits;
@@ -476,6 +483,7 @@
 	int length;
 	struct buffer_head map_bh;
 	loff_t i_size = i_size_read(inode);
+	int ret = 0;
 
 	if (page_has_buffers(page)) {
 		struct buffer_head *head = page_buffers(page);
@@ -538,7 +546,7 @@
 
 		map_bh.b_state = 0;
 		map_bh.b_size = 1 << blkbits;
-		if (get_block(inode, block_in_file, &map_bh, 1))
+		if (mpd->get_block(inode, block_in_file, &map_bh, 1))
 			goto confused;
 		if (buffer_new(&map_bh))
 			unmap_underlying_metadata(map_bh.b_bdev,
@@ -584,7 +592,7 @@
 	/*
 	 * This page will go to BIO.  Do we need to send this BIO off first?
 	 */
-	if (bio && *last_block_in_bio != blocks[0] - 1)
+	if (bio && mpd->last_block_in_bio != blocks[0] - 1)
 		bio = mpage_bio_submit(WRITE, bio);
 
 alloc_new:
@@ -641,7 +649,7 @@
 					boundary_block, 1 << blkbits);
 		}
 	} else {
-		*last_block_in_bio = blocks[blocks_per_page - 1];
+		mpd->last_block_in_bio = blocks[blocks_per_page - 1];
 	}
 	goto out;
 
@@ -649,18 +657,19 @@
 	if (bio)
 		bio = mpage_bio_submit(WRITE, bio);
 
-	if (writepage_fn) {
-		*ret = (*writepage_fn)(page, wbc);
+	if (mpd->use_writepage) {
+		ret = mapping->a_ops->writepage(page, wbc);
 	} else {
-		*ret = -EAGAIN;
+		ret = -EAGAIN;
 		goto out;
 	}
 	/*
 	 * The caller has a ref on the inode, so *mapping is stable
 	 */
-	mapping_set_error(mapping, *ret);
+	mapping_set_error(mapping, ret);
 out:
-	return bio;
+	mpd->bio = bio;
+	return ret;
 }
 
 /**
@@ -683,120 +692,27 @@
  * the call was made get new I/O started against them.  If wbc->sync_mode is
  * WB_SYNC_ALL then we were called for data integrity and we must wait for
  * existing IO to complete.
- *
- * If you fix this you should check generic_writepages() also!
  */
 int
 mpage_writepages(struct address_space *mapping,
 		struct writeback_control *wbc, get_block_t get_block)
 {
-	struct backing_dev_info *bdi = mapping->backing_dev_info;
-	struct bio *bio = NULL;
-	sector_t last_block_in_bio = 0;
-	int ret = 0;
-	int done = 0;
-	int (*writepage)(struct page *page, struct writeback_control *wbc);
-	struct pagevec pvec;
-	int nr_pages;
-	pgoff_t index;
-	pgoff_t end;		/* Inclusive */
-	int scanned = 0;
-	int range_whole = 0;
+	int ret;
 
-	if (wbc->nonblocking && bdi_write_congested(bdi)) {
-		wbc->encountered_congestion = 1;
-		return 0;
+	if (!get_block)
+		ret = generic_writepages(mapping, wbc);
+	else {
+		struct mpage_data mpd = {
+			.bio = NULL,
+			.last_block_in_bio = 0,
+			.get_block = get_block,
+			.use_writepage = 1,
+		};
+
+		ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd);
+		if (mpd.bio)
+			mpage_bio_submit(WRITE, mpd.bio);
 	}
-
-	writepage = NULL;
-	if (get_block == NULL)
-		writepage = mapping->a_ops->writepage;
-
-	pagevec_init(&pvec, 0);
-	if (wbc->range_cyclic) {
-		index = mapping->writeback_index; /* Start from prev offset */
-		end = -1;
-	} else {
-		index = wbc->range_start >> PAGE_CACHE_SHIFT;
-		end = wbc->range_end >> PAGE_CACHE_SHIFT;
-		if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
-			range_whole = 1;
-		scanned = 1;
-	}
-retry:
-	while (!done && (index <= end) &&
-			(nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
-			PAGECACHE_TAG_DIRTY,
-			min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1))) {
-		unsigned i;
-
-		scanned = 1;
-		for (i = 0; i < nr_pages; i++) {
-			struct page *page = pvec.pages[i];
-
-			/*
-			 * At this point we hold neither mapping->tree_lock nor
-			 * lock on the page itself: the page may be truncated or
-			 * invalidated (changing page->mapping to NULL), or even
-			 * swizzled back from swapper_space to tmpfs file
-			 * mapping
-			 */
-
-			lock_page(page);
-
-			if (unlikely(page->mapping != mapping)) {
-				unlock_page(page);
-				continue;
-			}
-
-			if (!wbc->range_cyclic && page->index > end) {
-				done = 1;
-				unlock_page(page);
-				continue;
-			}
-
-			if (wbc->sync_mode != WB_SYNC_NONE)
-				wait_on_page_writeback(page);
-
-			if (PageWriteback(page) ||
-					!clear_page_dirty_for_io(page)) {
-				unlock_page(page);
-				continue;
-			}
-
-			if (writepage) {
-				ret = (*writepage)(page, wbc);
-				mapping_set_error(mapping, ret);
-			} else {
-				bio = __mpage_writepage(bio, page, get_block,
-						&last_block_in_bio, &ret, wbc,
-						page->mapping->a_ops->writepage);
-			}
-			if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
-				unlock_page(page);
-			if (ret || (--(wbc->nr_to_write) <= 0))
-				done = 1;
-			if (wbc->nonblocking && bdi_write_congested(bdi)) {
-				wbc->encountered_congestion = 1;
-				done = 1;
-			}
-		}
-		pagevec_release(&pvec);
-		cond_resched();
-	}
-	if (!scanned && !done) {
-		/*
-		 * We hit the last page and there is more work to be done: wrap
-		 * back to the start of the file
-		 */
-		scanned = 1;
-		index = 0;
-		goto retry;
-	}
-	if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
-		mapping->writeback_index = index;
-	if (bio)
-		mpage_bio_submit(WRITE, bio);
 	return ret;
 }
 EXPORT_SYMBOL(mpage_writepages);
@@ -804,15 +720,15 @@
 int mpage_writepage(struct page *page, get_block_t get_block,
 	struct writeback_control *wbc)
 {
-	int ret = 0;
-	struct bio *bio;
-	sector_t last_block_in_bio = 0;
-
-	bio = __mpage_writepage(NULL, page, get_block,
-			&last_block_in_bio, &ret, wbc, NULL);
-	if (bio)
-		mpage_bio_submit(WRITE, bio);
-
+	struct mpage_data mpd = {
+		.bio = NULL,
+		.last_block_in_bio = 0,
+		.get_block = get_block,
+		.use_writepage = 0,
+	};
+	int ret = __mpage_writepage(page, wbc, &mpd);
+	if (mpd.bio)
+		mpage_bio_submit(WRITE, mpd.bio);
 	return ret;
 }
 EXPORT_SYMBOL(mpage_writepage);
diff --git a/fs/namei.c b/fs/namei.c
index b3780e3..5e2d98d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1719,7 +1719,7 @@
 	 * It already exists.
 	 */
 	mutex_unlock(&dir->d_inode->i_mutex);
-	audit_inode_update(path.dentry->d_inode);
+	audit_inode(pathname, path.dentry->d_inode);
 
 	error = -EEXIST;
 	if (flag & O_EXCL)
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 2e975c0a..a93620c 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -144,7 +144,8 @@
 };
 
 static struct kset mlog_kset = {
-	.kobj   = {.name = "logmask", .ktype = &mlog_ktype},
+	.kobj  = {.name = "logmask"},
+	.ktype = &mlog_ktype
 };
 
 int mlog_sys_init(struct kset *o2cb_subsys)
@@ -157,7 +158,7 @@
 	}
 	mlog_attr_ptrs[i] = NULL;
 
-	kobj_set_kset_s(&mlog_kset, o2cb_subsys);
+	kobj_set_kset_s(&mlog_kset, *o2cb_subsys);
 	return kset_register(&mlog_kset);
 }
 
diff --git a/fs/partitions/Kconfig b/fs/partitions/Kconfig
index 0120704..7638a1c 100644
--- a/fs/partitions/Kconfig
+++ b/fs/partitions/Kconfig
@@ -239,7 +239,7 @@
 
 config SYSV68_PARTITION
 	bool "SYSV68 partition table support" if PARTITION_ADVANCED
-	default y if M68K
+	default y if VME
 	help
 	  Say Y here if you would like to be able to read the hard disk
 	  partition table format used by Motorola Delta machines (using
diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
index 1bea610..e7b0700 100644
--- a/fs/partitions/efi.c
+++ b/fs/partitions/efi.c
@@ -152,7 +152,7 @@
 }
 
 static inline int
-pmbr_part_valid(struct partition *part, u64 lastlba)
+pmbr_part_valid(struct partition *part)
 {
         if (part->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT &&
             le32_to_cpu(part->start_sect) == 1UL)
@@ -163,7 +163,6 @@
 /**
  * is_pmbr_valid(): test Protective MBR for validity
  * @mbr: pointer to a legacy mbr structure
- * @lastlba: last_lba for the whole device
  *
  * Description: Returns 1 if PMBR is valid, 0 otherwise.
  * Validity depends on two things:
@@ -171,13 +170,13 @@
  *  2) One partition of type 0xEE is found
  */
 static int
-is_pmbr_valid(legacy_mbr *mbr, u64 lastlba)
+is_pmbr_valid(legacy_mbr *mbr)
 {
 	int i;
 	if (!mbr || le16_to_cpu(mbr->signature) != MSDOS_MBR_SIGNATURE)
                 return 0;
 	for (i = 0; i < 4; i++)
-		if (pmbr_part_valid(&mbr->partition_record[i], lastlba))
+		if (pmbr_part_valid(&mbr->partition_record[i]))
                         return 1;
 	return 0;
 }
@@ -516,7 +515,7 @@
 	int good_pgpt = 0, good_agpt = 0, good_pmbr = 0;
 	gpt_header *pgpt = NULL, *agpt = NULL;
 	gpt_entry *pptes = NULL, *aptes = NULL;
-	legacy_mbr *legacymbr = NULL;
+	legacy_mbr *legacymbr;
 	u64 lastlba;
 	if (!bdev || !gpt || !ptes)
 		return 0;
@@ -528,9 +527,8 @@
                 if (legacymbr) {
                         read_lba(bdev, 0, (u8 *) legacymbr,
                                  sizeof (*legacymbr));
-                        good_pmbr = is_pmbr_valid(legacymbr, lastlba);
+                        good_pmbr = is_pmbr_valid(legacymbr);
                         kfree(legacymbr);
-                        legacymbr=NULL;
                 }
                 if (!good_pmbr)
                         goto fail;
diff --git a/fs/signalfd.c b/fs/signalfd.c
new file mode 100644
index 0000000..7cfeab4
--- /dev/null
+++ b/fs/signalfd.c
@@ -0,0 +1,349 @@
+/*
+ *  fs/signalfd.c
+ *
+ *  Copyright (C) 2003  Linus Torvalds
+ *
+ *  Mon Mar 5, 2007: Davide Libenzi <davidel@xmailserver.org>
+ *      Changed ->read() to return a siginfo strcture instead of signal number.
+ *      Fixed locking in ->poll().
+ *      Added sighand-detach notification.
+ *      Added fd re-use in sys_signalfd() syscall.
+ *      Now using anonymous inode source.
+ *      Thanks to Oleg Nesterov for useful code review and suggestions.
+ *      More comments and suggestions from Arnd Bergmann.
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/list.h>
+#include <linux/anon_inodes.h>
+#include <linux/signalfd.h>
+
+struct signalfd_ctx {
+	struct list_head lnk;
+	wait_queue_head_t wqh;
+	sigset_t sigmask;
+	struct task_struct *tsk;
+};
+
+struct signalfd_lockctx {
+	struct task_struct *tsk;
+	unsigned long flags;
+};
+
+/*
+ * Tries to acquire the sighand lock. We do not increment the sighand
+ * use count, and we do not even pin the task struct, so we need to
+ * do it inside an RCU read lock, and we must be prepared for the
+ * ctx->tsk going to NULL (in signalfd_deliver()), and for the sighand
+ * being detached. We return 0 if the sighand has been detached, or
+ * 1 if we were able to pin the sighand lock.
+ */
+static int signalfd_lock(struct signalfd_ctx *ctx, struct signalfd_lockctx *lk)
+{
+	struct sighand_struct *sighand = NULL;
+
+	rcu_read_lock();
+	lk->tsk = rcu_dereference(ctx->tsk);
+	if (likely(lk->tsk != NULL))
+		sighand = lock_task_sighand(lk->tsk, &lk->flags);
+	rcu_read_unlock();
+
+	if (sighand && !ctx->tsk) {
+		unlock_task_sighand(lk->tsk, &lk->flags);
+		sighand = NULL;
+	}
+
+	return sighand != NULL;
+}
+
+static void signalfd_unlock(struct signalfd_lockctx *lk)
+{
+	unlock_task_sighand(lk->tsk, &lk->flags);
+}
+
+/*
+ * This must be called with the sighand lock held.
+ */
+void signalfd_deliver(struct task_struct *tsk, int sig)
+{
+	struct sighand_struct *sighand = tsk->sighand;
+	struct signalfd_ctx *ctx, *tmp;
+
+	BUG_ON(!sig);
+	list_for_each_entry_safe(ctx, tmp, &sighand->signalfd_list, lnk) {
+		/*
+		 * We use a negative signal value as a way to broadcast that the
+		 * sighand has been orphaned, so that we can notify all the
+		 * listeners about this. Remember the ctx->sigmask is inverted,
+		 * so if the user is interested in a signal, that corresponding
+		 * bit will be zero.
+		 */
+		if (sig < 0) {
+			if (ctx->tsk == tsk) {
+				ctx->tsk = NULL;
+				list_del_init(&ctx->lnk);
+				wake_up(&ctx->wqh);
+			}
+		} else {
+			if (!sigismember(&ctx->sigmask, sig))
+				wake_up(&ctx->wqh);
+		}
+	}
+}
+
+static void signalfd_cleanup(struct signalfd_ctx *ctx)
+{
+	struct signalfd_lockctx lk;
+
+	/*
+	 * This is tricky. If the sighand is gone, we do not need to remove
+	 * context from the list, the list itself won't be there anymore.
+	 */
+	if (signalfd_lock(ctx, &lk)) {
+		list_del(&ctx->lnk);
+		signalfd_unlock(&lk);
+	}
+	kfree(ctx);
+}
+
+static int signalfd_release(struct inode *inode, struct file *file)
+{
+	signalfd_cleanup(file->private_data);
+	return 0;
+}
+
+static unsigned int signalfd_poll(struct file *file, poll_table *wait)
+{
+	struct signalfd_ctx *ctx = file->private_data;
+	unsigned int events = 0;
+	struct signalfd_lockctx lk;
+
+	poll_wait(file, &ctx->wqh, wait);
+
+	/*
+	 * Let the caller get a POLLIN in this case, ala socket recv() when
+	 * the peer disconnects.
+	 */
+	if (signalfd_lock(ctx, &lk)) {
+		if (next_signal(&lk.tsk->pending, &ctx->sigmask) > 0 ||
+		    next_signal(&lk.tsk->signal->shared_pending,
+				&ctx->sigmask) > 0)
+			events |= POLLIN;
+		signalfd_unlock(&lk);
+	} else
+		events |= POLLIN;
+
+	return events;
+}
+
+/*
+ * Copied from copy_siginfo_to_user() in kernel/signal.c
+ */
+static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
+			     siginfo_t const *kinfo)
+{
+	long err;
+
+	BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
+
+	/*
+	 * Unused memebers should be zero ...
+	 */
+	err = __clear_user(uinfo, sizeof(*uinfo));
+
+	/*
+	 * If you change siginfo_t structure, please be sure
+	 * this code is fixed accordingly.
+	 */
+	err |= __put_user(kinfo->si_signo, &uinfo->signo);
+	err |= __put_user(kinfo->si_errno, &uinfo->err);
+	err |= __put_user((short)kinfo->si_code, &uinfo->code);
+	switch (kinfo->si_code & __SI_MASK) {
+	case __SI_KILL:
+		err |= __put_user(kinfo->si_pid, &uinfo->pid);
+		err |= __put_user(kinfo->si_uid, &uinfo->uid);
+		break;
+	case __SI_TIMER:
+		 err |= __put_user(kinfo->si_tid, &uinfo->tid);
+		 err |= __put_user(kinfo->si_overrun, &uinfo->overrun);
+		 err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr);
+		break;
+	case __SI_POLL:
+		err |= __put_user(kinfo->si_band, &uinfo->band);
+		err |= __put_user(kinfo->si_fd, &uinfo->fd);
+		break;
+	case __SI_FAULT:
+		err |= __put_user((long)kinfo->si_addr, &uinfo->addr);
+#ifdef __ARCH_SI_TRAPNO
+		err |= __put_user(kinfo->si_trapno, &uinfo->trapno);
+#endif
+		break;
+	case __SI_CHLD:
+		err |= __put_user(kinfo->si_pid, &uinfo->pid);
+		err |= __put_user(kinfo->si_uid, &uinfo->uid);
+		err |= __put_user(kinfo->si_status, &uinfo->status);
+		err |= __put_user(kinfo->si_utime, &uinfo->utime);
+		err |= __put_user(kinfo->si_stime, &uinfo->stime);
+		break;
+	case __SI_RT: /* This is not generated by the kernel as of now. */
+	case __SI_MESGQ: /* But this is */
+		err |= __put_user(kinfo->si_pid, &uinfo->pid);
+		err |= __put_user(kinfo->si_uid, &uinfo->uid);
+		err |= __put_user((long)kinfo->si_ptr, &uinfo->svptr);
+		break;
+	default: /* this is just in case for now ... */
+		err |= __put_user(kinfo->si_pid, &uinfo->pid);
+		err |= __put_user(kinfo->si_uid, &uinfo->uid);
+		break;
+	}
+
+	return err ? -EFAULT: sizeof(*uinfo);
+}
+
+/*
+ * Returns either the size of a "struct signalfd_siginfo", or zero if the
+ * sighand we are attached to, has been orphaned. The "count" parameter
+ * must be at least the size of a "struct signalfd_siginfo".
+ */
+static ssize_t signalfd_read(struct file *file, char __user *buf, size_t count,
+			     loff_t *ppos)
+{
+	struct signalfd_ctx *ctx = file->private_data;
+	ssize_t res = 0;
+	int locked, signo;
+	siginfo_t info;
+	struct signalfd_lockctx lk;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (count < sizeof(struct signalfd_siginfo))
+		return -EINVAL;
+	locked = signalfd_lock(ctx, &lk);
+	if (!locked)
+		return 0;
+	res = -EAGAIN;
+	signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
+	if (signo == 0 && !(file->f_flags & O_NONBLOCK)) {
+		add_wait_queue(&ctx->wqh, &wait);
+		for (;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			signo = dequeue_signal(lk.tsk, &ctx->sigmask, &info);
+			if (signo != 0)
+				break;
+			if (signal_pending(current)) {
+				res = -ERESTARTSYS;
+				break;
+			}
+			signalfd_unlock(&lk);
+			schedule();
+			locked = signalfd_lock(ctx, &lk);
+			if (unlikely(!locked)) {
+				/*
+				 * Let the caller read zero byte, ala socket
+				 * recv() when the peer disconnect. This test
+				 * must be done before doing a dequeue_signal(),
+				 * because if the sighand has been orphaned,
+				 * the dequeue_signal() call is going to crash.
+				 */
+				res = 0;
+				break;
+			}
+		}
+		remove_wait_queue(&ctx->wqh, &wait);
+		__set_current_state(TASK_RUNNING);
+	}
+	if (likely(locked))
+		signalfd_unlock(&lk);
+	if (likely(signo))
+		res = signalfd_copyinfo((struct signalfd_siginfo __user *) buf,
+					&info);
+
+	return res;
+}
+
+static const struct file_operations signalfd_fops = {
+	.release	= signalfd_release,
+	.poll		= signalfd_poll,
+	.read		= signalfd_read,
+};
+
+/*
+ * Create a file descriptor that is associated with our signal
+ * state. We can pass it around to others if we want to, but
+ * it will always be _our_ signal state.
+ */
+asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask)
+{
+	int error;
+	sigset_t sigmask;
+	struct signalfd_ctx *ctx;
+	struct sighand_struct *sighand;
+	struct file *file;
+	struct inode *inode;
+	struct signalfd_lockctx lk;
+
+	if (sizemask != sizeof(sigset_t) ||
+	    copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
+		return error = -EINVAL;
+	sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+	signotset(&sigmask);
+
+	if (ufd == -1) {
+		ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+		if (!ctx)
+			return -ENOMEM;
+
+		init_waitqueue_head(&ctx->wqh);
+		ctx->sigmask = sigmask;
+		ctx->tsk = current;
+
+		sighand = current->sighand;
+		/*
+		 * Add this fd to the list of signal listeners.
+		 */
+		spin_lock_irq(&sighand->siglock);
+		list_add_tail(&ctx->lnk, &sighand->signalfd_list);
+		spin_unlock_irq(&sighand->siglock);
+
+		/*
+		 * When we call this, the initialization must be complete, since
+		 * anon_inode_getfd() will install the fd.
+		 */
+		error = anon_inode_getfd(&ufd, &inode, &file, "[signalfd]",
+					 &signalfd_fops, ctx);
+		if (error)
+			goto err_fdalloc;
+	} else {
+		file = fget(ufd);
+		if (!file)
+			return -EBADF;
+		ctx = file->private_data;
+		if (file->f_op != &signalfd_fops) {
+			fput(file);
+			return -EINVAL;
+		}
+		/*
+		 * We need to be prepared of the fact that the sighand this fd
+		 * is attached to, has been detched. In that case signalfd_lock()
+		 * will return 0, and we'll just skip setting the new mask.
+		 */
+		if (signalfd_lock(ctx, &lk)) {
+			ctx->sigmask = sigmask;
+			signalfd_unlock(&lk);
+		}
+		wake_up(&ctx->wqh);
+		fput(file);
+	}
+
+	return ufd;
+
+err_fdalloc:
+	signalfd_cleanup(ctx);
+	return error;
+}
+
diff --git a/fs/timerfd.c b/fs/timerfd.c
new file mode 100644
index 0000000..e329e37
--- /dev/null
+++ b/fs/timerfd.c
@@ -0,0 +1,227 @@
+/*
+ *  fs/timerfd.c
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ *
+ *  Thanks to Thomas Gleixner for code reviews and useful comments.
+ *
+ */
+
+#include <linux/file.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+#include <linux/hrtimer.h>
+#include <linux/anon_inodes.h>
+#include <linux/timerfd.h>
+
+struct timerfd_ctx {
+	struct hrtimer tmr;
+	ktime_t tintv;
+	spinlock_t lock;
+	wait_queue_head_t wqh;
+	int expired;
+};
+
+/*
+ * This gets called when the timer event triggers. We set the "expired"
+ * flag, but we do not re-arm the timer (in case it's necessary,
+ * tintv.tv64 != 0) until the timer is read.
+ */
+static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
+{
+	struct timerfd_ctx *ctx = container_of(htmr, struct timerfd_ctx, tmr);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->lock, flags);
+	ctx->expired = 1;
+	wake_up_locked(&ctx->wqh);
+	spin_unlock_irqrestore(&ctx->lock, flags);
+
+	return HRTIMER_NORESTART;
+}
+
+static void timerfd_setup(struct timerfd_ctx *ctx, int clockid, int flags,
+			  const struct itimerspec *ktmr)
+{
+	enum hrtimer_mode htmode;
+	ktime_t texp;
+
+	htmode = (flags & TFD_TIMER_ABSTIME) ?
+		HRTIMER_MODE_ABS: HRTIMER_MODE_REL;
+
+	texp = timespec_to_ktime(ktmr->it_value);
+	ctx->expired = 0;
+	ctx->tintv = timespec_to_ktime(ktmr->it_interval);
+	hrtimer_init(&ctx->tmr, clockid, htmode);
+	ctx->tmr.expires = texp;
+	ctx->tmr.function = timerfd_tmrproc;
+	if (texp.tv64 != 0)
+		hrtimer_start(&ctx->tmr, texp, htmode);
+}
+
+static int timerfd_release(struct inode *inode, struct file *file)
+{
+	struct timerfd_ctx *ctx = file->private_data;
+
+	hrtimer_cancel(&ctx->tmr);
+	kfree(ctx);
+	return 0;
+}
+
+static unsigned int timerfd_poll(struct file *file, poll_table *wait)
+{
+	struct timerfd_ctx *ctx = file->private_data;
+	unsigned int events = 0;
+	unsigned long flags;
+
+	poll_wait(file, &ctx->wqh, wait);
+
+	spin_lock_irqsave(&ctx->lock, flags);
+	if (ctx->expired)
+		events |= POLLIN;
+	spin_unlock_irqrestore(&ctx->lock, flags);
+
+	return events;
+}
+
+static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
+			    loff_t *ppos)
+{
+	struct timerfd_ctx *ctx = file->private_data;
+	ssize_t res;
+	u32 ticks = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (count < sizeof(ticks))
+		return -EINVAL;
+	spin_lock_irq(&ctx->lock);
+	res = -EAGAIN;
+	if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) {
+		__add_wait_queue(&ctx->wqh, &wait);
+		for (res = 0;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			if (ctx->expired) {
+				res = 0;
+				break;
+			}
+			if (signal_pending(current)) {
+				res = -ERESTARTSYS;
+				break;
+			}
+			spin_unlock_irq(&ctx->lock);
+			schedule();
+			spin_lock_irq(&ctx->lock);
+		}
+		__remove_wait_queue(&ctx->wqh, &wait);
+		__set_current_state(TASK_RUNNING);
+	}
+	if (ctx->expired) {
+		ctx->expired = 0;
+		if (ctx->tintv.tv64 != 0) {
+			/*
+			 * If tintv.tv64 != 0, this is a periodic timer that
+			 * needs to be re-armed. We avoid doing it in the timer
+			 * callback to avoid DoS attacks specifying a very
+			 * short timer period.
+			 */
+			ticks = (u32)
+				hrtimer_forward(&ctx->tmr,
+						hrtimer_cb_get_time(&ctx->tmr),
+						ctx->tintv);
+			hrtimer_restart(&ctx->tmr);
+		} else
+			ticks = 1;
+	}
+	spin_unlock_irq(&ctx->lock);
+	if (ticks)
+		res = put_user(ticks, buf) ? -EFAULT: sizeof(ticks);
+	return res;
+}
+
+static const struct file_operations timerfd_fops = {
+	.release	= timerfd_release,
+	.poll		= timerfd_poll,
+	.read		= timerfd_read,
+};
+
+asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+			    const struct itimerspec __user *utmr)
+{
+	int error;
+	struct timerfd_ctx *ctx;
+	struct file *file;
+	struct inode *inode;
+	struct itimerspec ktmr;
+
+	if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
+		return -EFAULT;
+
+	if (clockid != CLOCK_MONOTONIC &&
+	    clockid != CLOCK_REALTIME)
+		return -EINVAL;
+	if (!timespec_valid(&ktmr.it_value) ||
+	    !timespec_valid(&ktmr.it_interval))
+		return -EINVAL;
+
+	if (ufd == -1) {
+		ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+		if (!ctx)
+			return -ENOMEM;
+
+		init_waitqueue_head(&ctx->wqh);
+		spin_lock_init(&ctx->lock);
+
+		timerfd_setup(ctx, clockid, flags, &ktmr);
+
+		/*
+		 * When we call this, the initialization must be complete, since
+		 * anon_inode_getfd() will install the fd.
+		 */
+		error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]",
+					 &timerfd_fops, ctx);
+		if (error)
+			goto err_tmrcancel;
+	} else {
+		file = fget(ufd);
+		if (!file)
+			return -EBADF;
+		ctx = file->private_data;
+		if (file->f_op != &timerfd_fops) {
+			fput(file);
+			return -EINVAL;
+		}
+		/*
+		 * We need to stop the existing timer before reprogramming
+		 * it to the new values.
+		 */
+		for (;;) {
+			spin_lock_irq(&ctx->lock);
+			if (hrtimer_try_to_cancel(&ctx->tmr) >= 0)
+				break;
+			spin_unlock_irq(&ctx->lock);
+			cpu_relax();
+		}
+		/*
+		 * Re-program the timer to the new value ...
+		 */
+		timerfd_setup(ctx, clockid, flags, &ktmr);
+
+		spin_unlock_irq(&ctx->lock);
+		fput(file);
+	}
+
+	return ufd;
+
+err_tmrcancel:
+	hrtimer_cancel(&ctx->tmr);
+	kfree(ctx);
+	return error;
+}
+
diff --git a/fs/xattr.c b/fs/xattr.c
index 9f4568b..4523aca 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -350,6 +350,7 @@
 	f = fget(fd);
 	if (!f)
 		return error;
+	audit_inode(NULL, f->f_path.dentry->d_inode);
 	error = getxattr(f->f_path.dentry, name, value, size);
 	fput(f);
 	return error;
@@ -422,6 +423,7 @@
 	f = fget(fd);
 	if (!f)
 		return error;
+	audit_inode(NULL, f->f_path.dentry->d_inode);
 	error = listxattr(f->f_path.dentry, list, size);
 	fput(f);
 	return error;
diff --git a/include/acpi/acdispat.h b/include/acpi/acdispat.h
index cb8d286..7f690bb 100644
--- a/include/acpi/acdispat.h
+++ b/include/acpi/acdispat.h
@@ -290,12 +290,9 @@
 acpi_status
 acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state);
 
-struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
-						  union acpi_parse_object
-						  *origin,
-						  union acpi_operand_object
-						  *mth_desc,
-						  struct acpi_thread_state
+struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object
+						  *origin, union acpi_operand_object
+						  *mth_desc, struct acpi_thread_state
 						  *thread);
 
 acpi_status
diff --git a/include/acpi/acglobal.h b/include/acpi/acglobal.h
index 24c3f05..347a911 100644
--- a/include/acpi/acglobal.h
+++ b/include/acpi/acglobal.h
@@ -319,7 +319,7 @@
     acpi_gbl_fixed_event_handlers[ACPI_NUM_FIXED_EVENTS];
 ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
 ACPI_EXTERN struct acpi_gpe_block_info
-    *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
+*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
 
 /*****************************************************************************
  *
diff --git a/include/acpi/acinterp.h b/include/acpi/acinterp.h
index 4409830..ce7c9d6 100644
--- a/include/acpi/acinterp.h
+++ b/include/acpi/acinterp.h
@@ -253,8 +253,7 @@
 
 void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread);
 
-void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc,
-			  struct acpi_thread_state *thread);
+void acpi_ex_unlink_mutex(union acpi_operand_object *obj_desc);
 
 /*
  * exprep - ACPI AML execution - prep utilities
@@ -446,10 +445,14 @@
 /*
  * exutils - interpreter/scanner utilities
  */
-acpi_status acpi_ex_enter_interpreter(void);
+void acpi_ex_enter_interpreter(void);
 
 void acpi_ex_exit_interpreter(void);
 
+void acpi_ex_reacquire_interpreter(void);
+
+void acpi_ex_relinquish_interpreter(void);
+
 void acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc);
 
 u8 acpi_ex_acquire_global_lock(u32 rule);
diff --git a/include/acpi/aclocal.h b/include/acpi/aclocal.h
index 6f83ddb..202cd42 100644
--- a/include/acpi/aclocal.h
+++ b/include/acpi/aclocal.h
@@ -630,7 +630,7 @@
  * and bytelists.
  */
 struct acpi_parse_obj_named {
-	ACPI_PARSE_COMMON u8 * path;
+	ACPI_PARSE_COMMON u8 *path;
 	u8 *data;		/* AML body or bytelist data */
 	u32 length;		/* AML length */
 	u32 name;		/* 4-byte name or zero if no name */
diff --git a/include/acpi/acnamesp.h b/include/acpi/acnamesp.h
index 535b7e1..5ef38a6 100644
--- a/include/acpi/acnamesp.h
+++ b/include/acpi/acnamesp.h
@@ -100,10 +100,8 @@
 		       acpi_walk_callback user_function,
 		       void *context, void **return_value);
 
-struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type,
-						  struct acpi_namespace_node
-						  *parent,
-						  struct acpi_namespace_node
+struct acpi_namespace_node *acpi_ns_get_next_node(acpi_object_type type, struct acpi_namespace_node
+						  *parent, struct acpi_namespace_node
 						  *child);
 
 /*
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 5206d61..7e1211a 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -155,7 +155,7 @@
 struct acpi_object_mutex {
 	ACPI_OBJECT_COMMON_HEADER u8 sync_level;	/* 0-15, specified in Mutex() call */
 	u16 acquisition_depth;	/* Allow multiple Acquires, same thread */
-	acpi_thread_id owner_thread_id;	/* Current owner of the mutex */
+	struct acpi_thread_state *owner_thread;	/* Current owner of the mutex */
 	acpi_mutex os_mutex;	/* Actual OS synchronization object */
 	union acpi_operand_object *prev;	/* Link for list of acquired mutexes */
 	union acpi_operand_object *next;	/* Link for list of acquired mutexes */
@@ -216,7 +216,7 @@
 	    /* The next two fields take advantage of the 3-byte space before NOTIFY_INFO */
 	u8 proc_id;
 	u8 length;
-	 ACPI_COMMON_NOTIFY_INFO acpi_io_address address;
+	ACPI_COMMON_NOTIFY_INFO acpi_io_address address;
 };
 
 struct acpi_object_thermal_zone {
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 9cfd5b1..c6fa5e0 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -91,7 +91,8 @@
 typedef int (*acpi_op_lock) (struct acpi_device * device, int type);
 typedef int (*acpi_op_start) (struct acpi_device * device);
 typedef int (*acpi_op_stop) (struct acpi_device * device, int type);
-typedef int (*acpi_op_suspend) (struct acpi_device * device, pm_message_t state);
+typedef int (*acpi_op_suspend) (struct acpi_device * device,
+				pm_message_t state);
 typedef int (*acpi_op_resume) (struct acpi_device * device);
 typedef int (*acpi_op_scan) (struct acpi_device * device);
 typedef int (*acpi_op_bind) (struct acpi_device * device);
@@ -296,7 +297,7 @@
 	void *driver_data;
 	struct device dev;
 	struct acpi_bus_ops bus_ops;	/* workaround for different code path for hotplug */
-	enum acpi_bus_removal_type removal_type; /* indicate for different removal type */
+	enum acpi_bus_removal_type removal_type;	/* indicate for different removal type */
 };
 
 #define acpi_driver_data(d)	((d)->driver_data)
@@ -338,7 +339,7 @@
 		 acpi_handle handle, int type);
 int acpi_bus_trim(struct acpi_device *start, int rmdevice);
 int acpi_bus_start(struct acpi_device *device);
-acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd);
+acpi_status acpi_bus_get_ejd(acpi_handle handle, acpi_handle * ejd);
 int acpi_match_ids(struct acpi_device *device, char *ids);
 int acpi_create_dir(struct acpi_device *);
 void acpi_remove_dir(struct acpi_device *);
@@ -363,6 +364,6 @@
 acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int);
 #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
 
-#endif /* CONFIG_ACPI */
+#endif				/* CONFIG_ACPI */
 
 #endif /*__ACPI_BUS_H__*/
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index f6275b0..5535159 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -113,7 +113,8 @@
 extern int register_dock_notifier(struct notifier_block *nb);
 extern void unregister_dock_notifier(struct notifier_block *nb);
 extern int register_hotplug_dock_device(acpi_handle handle,
-	acpi_notify_handler handler, void *context);
+					acpi_notify_handler handler,
+					void *context);
 extern void unregister_hotplug_dock_device(acpi_handle handle);
 #else
 static inline int is_dock_device(acpi_handle handle)
@@ -128,7 +129,8 @@
 {
 }
 static inline int register_hotplug_dock_device(acpi_handle handle,
-				acpi_notify_handler handler, void *context)
+					       acpi_notify_handler handler,
+					       void *context)
 {
 	return -ENODEV;
 }
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index 1049f2a..f9d2bde 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -8,7 +8,7 @@
 #if MAX_NUMNODES > 256
 #define MAX_PXM_DOMAINS MAX_NUMNODES
 #else
-#define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */
+#define MAX_PXM_DOMAINS (256)	/* Old pxm spec is defined 8 bit */
 #endif
 
 extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS];
diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h
index 2785058..5e07db0 100644
--- a/include/acpi/acpiosxf.h
+++ b/include/acpi/acpiosxf.h
@@ -143,7 +143,8 @@
  */
 void *acpi_os_allocate(acpi_size size);
 
-void __iomem *acpi_os_map_memory(acpi_physical_address where, acpi_native_uint length);
+void __iomem *acpi_os_map_memory(acpi_physical_address where,
+				 acpi_native_uint length);
 
 void acpi_os_unmap_memory(void __iomem * logical_address, acpi_size size);
 
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 56bf492..fe8abc2 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -344,7 +344,7 @@
 
 /* 64-bit integers */
 
-typedef unsigned long long              acpi_integer;
+typedef unsigned long long acpi_integer;
 #define ACPI_INTEGER_MAX                ACPI_UINT64_MAX
 #define ACPI_INTEGER_BIT_SIZE           64
 #define ACPI_MAX_DECIMAL_DIGITS         20	/* 2^64 = 18,446,744,073,709,551,616 */
diff --git a/include/acpi/acutils.h b/include/acpi/acutils.h
index 883ffe9..15a8388 100644
--- a/include/acpi/acutils.h
+++ b/include/acpi/acutils.h
@@ -498,7 +498,8 @@
 acpi_status
 acpi_ut_walk_aml_resources(u8 * aml,
 			   acpi_size aml_length,
-			   acpi_walk_aml_callback user_function, void **context);
+			   acpi_walk_aml_callback user_function,
+			   void **context);
 
 acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index);
 
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h
index 5f532d2..a568717 100644
--- a/include/acpi/platform/aclinux.h
+++ b/include/acpi/platform/aclinux.h
@@ -103,7 +103,10 @@
 
 #define acpi_thread_id struct task_struct *
 
-static inline acpi_thread_id acpi_os_get_thread_id(void) { return current; }
+static inline acpi_thread_id acpi_os_get_thread_id(void)
+{
+	return current;
+}
 
 /*
  * The irqs_disabled() check is for resume from RAM.
@@ -112,15 +115,19 @@
  * to quiet __might_sleep() in kmalloc() and resume does not.
  */
 #include <acpi/actypes.h>
-static inline void *acpi_os_allocate(acpi_size size) {
-	return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+static inline void *acpi_os_allocate(acpi_size size)
+{
+	return kmalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
 }
-static inline void *acpi_os_allocate_zeroed(acpi_size size) {
-	return kzalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+static inline void *acpi_os_allocate_zeroed(acpi_size size)
+{
+	return kzalloc(size, irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
 }
 
-static inline void *acpi_os_acquire_object(acpi_cache_t * cache) {
-        return kmem_cache_zalloc(cache, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
+static inline void *acpi_os_acquire_object(acpi_cache_t * cache)
+{
+	return kmem_cache_zalloc(cache,
+				 irqs_disabled()? GFP_ATOMIC : GFP_KERNEL);
 }
 
 #define ACPI_ALLOCATE(a)	acpi_os_allocate(a)
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 916c010..b4b0ffd 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -18,7 +18,7 @@
 
 #define ACPI_PDC_REVISION_ID		0x1
 
-#define ACPI_PSD_REV0_REVISION		0 /* Support for _PSD as in ACPI 3.0 */
+#define ACPI_PSD_REV0_REVISION		0	/* Support for _PSD as in ACPI 3.0 */
 #define ACPI_PSD_REV0_ENTRIES		5
 
 /*
@@ -189,8 +189,9 @@
 	} piix4;
 };
 
-extern int acpi_processor_preregister_performance(
-		struct acpi_processor_performance **performance);
+extern int acpi_processor_preregister_performance(struct
+						  acpi_processor_performance
+						  **performance);
 
 extern int acpi_processor_register_performance(struct acpi_processor_performance
 					       *performance, unsigned int cpu);
@@ -213,7 +214,8 @@
 void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
 					unsigned int cpu);
 int acpi_processor_ffh_cstate_probe(unsigned int cpu,
-		struct acpi_processor_cx *cx, struct acpi_power_register *reg);
+				    struct acpi_processor_cx *cx,
+				    struct acpi_power_register *reg);
 void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cstate);
 #else
 static inline void acpi_processor_power_init_bm_check(struct
@@ -224,12 +226,14 @@
 	return;
 }
 static inline int acpi_processor_ffh_cstate_probe(unsigned int cpu,
-		struct acpi_processor_cx *cx, struct acpi_power_register *reg)
+						  struct acpi_processor_cx *cx,
+						  struct acpi_power_register
+						  *reg)
 {
 	return -1;
 }
-static inline void acpi_processor_ffh_cstate_enter(
-		struct acpi_processor_cx *cstate)
+static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
+						   *cstate)
 {
 	return;
 }
diff --git a/include/asm-alpha/poll.h b/include/asm-alpha/poll.h
index 76f8935..c98509d 100644
--- a/include/asm-alpha/poll.h
+++ b/include/asm-alpha/poll.h
@@ -1,25 +1 @@
-#ifndef __ALPHA_POLL_H
-#define __ALPHA_POLL_H
-
-#define POLLIN		(1 << 0)
-#define POLLPRI		(1 << 1)
-#define POLLOUT		(1 << 2)
-#define POLLERR		(1 << 3)
-#define POLLHUP		(1 << 4)
-#define POLLNVAL	(1 << 5)
-#define POLLRDNORM	(1 << 6)
-#define POLLRDBAND	(1 << 7)
-#define POLLWRNORM	(1 << 8)
-#define POLLWRBAND	(1 << 9)
-#define POLLMSG		(1 << 10)
-#define POLLREMOVE	(1 << 12)
-#define POLLRDHUP       (1 << 13)
-
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-arm/poll.h b/include/asm-arm/poll.h
index 5030b2b..c98509d 100644
--- a/include/asm-arm/poll.h
+++ b/include/asm-arm/poll.h
@@ -1,27 +1 @@
-#ifndef __ASMARM_POLL_H
-#define __ASMARM_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-arm26/poll.h b/include/asm-arm26/poll.h
index 9ccb7f4..1170e70 100644
--- a/include/asm-arm26/poll.h
+++ b/include/asm-arm26/poll.h
@@ -1,26 +1,8 @@
 #ifndef __ASMARM_POLL_H
 #define __ASMARM_POLL_H
 
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
+#include <asm-generic/poll.h>
 
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#undef POLLREMOVE
 
 #endif
diff --git a/include/asm-avr32/poll.h b/include/asm-avr32/poll.h
index 736e297..c98509d 100644
--- a/include/asm-avr32/poll.h
+++ b/include/asm-avr32/poll.h
@@ -1,27 +1 @@
-#ifndef __ASM_AVR32_POLL_H
-#define __ASM_AVR32_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP	0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif /* __ASM_AVR32_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-cris/poll.h b/include/asm-cris/poll.h
index 1b25d4c..c98509d 100644
--- a/include/asm-cris/poll.h
+++ b/include/asm-cris/poll.h
@@ -1,26 +1 @@
-#ifndef __ASM_CRIS_POLL_H
-#define __ASM_CRIS_POLL_H
-
-/* taken from asm-alpha */
-
-#define POLLIN		1
-#define POLLPRI		2
-#define POLLOUT		4
-#define POLLERR		8
-#define POLLHUP		16
-#define POLLNVAL	32
-#define POLLRDNORM	64
-#define POLLRDBAND	128
-#define POLLWRNORM	256
-#define POLLWRBAND	512
-#define POLLMSG		1024
-#define POLLREMOVE	4096
-#define POLLRDHUP       8192
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-frv/poll.h b/include/asm-frv/poll.h
index c8fe880..0d01479 100644
--- a/include/asm-frv/poll.h
+++ b/include/asm-frv/poll.h
@@ -1,24 +1,12 @@
 #ifndef _ASM_POLL_H
 #define _ASM_POLL_H
 
-#define POLLIN		  1
-#define POLLPRI		  2
-#define POLLOUT		  4
-#define POLLERR		  8
-#define POLLHUP		 16
-#define POLLNVAL	 32
-#define POLLRDNORM	 64
 #define POLLWRNORM	POLLOUT
-#define POLLRDBAND	128
 #define POLLWRBAND	256
-#define POLLMSG		0x0400
-#define POLLRDHUP       0x2000
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
+
+#undef POLLREMOVE
 
 #endif
 
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
index fa14f8c..5bfeef7 100644
--- a/include/asm-generic/Kbuild
+++ b/include/asm-generic/Kbuild
@@ -4,6 +4,7 @@
 header-y += ioctl.h
 header-y += ipc.h
 header-y += mman.h
+header-y += poll.h
 header-y += signal.h
 header-y += statfs.h
 
diff --git a/include/asm-generic/audit_signal.h b/include/asm-generic/audit_signal.h
new file mode 100644
index 0000000..6feab7f
--- /dev/null
+++ b/include/asm-generic/audit_signal.h
@@ -0,0 +1,3 @@
+__NR_kill,
+__NR_tgkill,
+__NR_tkill,
diff --git a/include/asm-generic/poll.h b/include/asm-generic/poll.h
new file mode 100644
index 0000000..44bce83
--- /dev/null
+++ b/include/asm-generic/poll.h
@@ -0,0 +1,37 @@
+#ifndef __ASM_GENERIC_POLL_H
+#define __ASM_GENERIC_POLL_H
+
+/* These are specified by iBCS2 */
+#define POLLIN		0x0001
+#define POLLPRI		0x0002
+#define POLLOUT		0x0004
+#define POLLERR		0x0008
+#define POLLHUP		0x0010
+#define POLLNVAL	0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#ifndef POLLWRNORM
+#define POLLWRNORM	0x0100
+#endif
+#ifndef POLLWRBAND
+#define POLLWRBAND	0x0200
+#endif
+#ifndef POLLMSG
+#define POLLMSG		0x0400
+#endif
+#ifndef POLLREMOVE
+#define POLLREMOVE	0x1000
+#endif
+#ifndef POLLRDHUP
+#define POLLRDHUP       0x2000
+#endif
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif	/* __ASM_GENERIC_POLL_H */
diff --git a/include/asm-h8300/poll.h b/include/asm-h8300/poll.h
index fc52103..f61540c 100644
--- a/include/asm-h8300/poll.h
+++ b/include/asm-h8300/poll.h
@@ -1,23 +1,11 @@
 #ifndef __H8300_POLL_H
 #define __H8300_POLL_H
 
-#define POLLIN		  1
-#define POLLPRI		  2
-#define POLLOUT		  4
-#define POLLERR		  8
-#define POLLHUP		 16
-#define POLLNVAL	 32
-#define POLLRDNORM	 64
 #define POLLWRNORM	POLLOUT
-#define POLLRDBAND	128
 #define POLLWRBAND	256
-#define POLLMSG		0x0400
-#define POLLRDHUP       0x2000
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
+
+#undef POLLREMOVE
 
 #endif
diff --git a/include/asm-h8300/unistd.h b/include/asm-h8300/unistd.h
index 7ddd414..99f3c35 100644
--- a/include/asm-h8300/unistd.h
+++ b/include/asm-h8300/unistd.h
@@ -21,7 +21,7 @@
 #define __NR_time		 13
 #define __NR_mknod		 14
 #define __NR_chmod		 15
-#define __NR_chown		 16
+#define __NR_lchown		 16
 #define __NR_break		 17
 #define __NR_oldstat		 18
 #define __NR_lseek		 19
@@ -115,10 +115,10 @@
 #define __NR_lstat		107
 #define __NR_fstat		108
 #define __NR_olduname		109
-#define __NR_iopl		/* 110 */ not supported
+#define __NR_iopl		110
 #define __NR_vhangup		111
-#define __NR_idle		/* 112 */ Obsolete
-#define __NR_vm86		/* 113 */ not supported
+#define __NR_idle		112
+#define __NR_vm86old		113
 #define __NR_wait4		114
 #define __NR_swapoff		115
 #define __NR_sysinfo		116
@@ -128,7 +128,7 @@
 #define __NR_clone		120
 #define __NR_setdomainname	121
 #define __NR_uname		122
-#define __NR_cacheflush		123
+#define __NR_modify_ldt		123
 #define __NR_adjtimex		124
 #define __NR_mprotect		125
 #define __NR_sigprocmask	126
@@ -171,7 +171,7 @@
 #define __NR_mremap		163
 #define __NR_setresuid		164
 #define __NR_getresuid		165
-#define __NR_getpagesize	166
+#define __NR_vm86		166
 #define __NR_query_module	167
 #define __NR_poll		168
 #define __NR_nfsservctl		169
@@ -187,7 +187,7 @@
 #define __NR_rt_sigsuspend	179
 #define __NR_pread64		180
 #define __NR_pwrite64		181
-#define __NR_lchown		182
+#define __NR_chown		182
 #define __NR_getcwd		183
 #define __NR_capget		184
 #define __NR_capset		185
@@ -203,7 +203,7 @@
 #define __NR_stat64		195
 #define __NR_lstat64		196
 #define __NR_fstat64		197
-#define __NR_chown32		198
+#define __NR_lchown32		198
 #define __NR_getuid32		199
 #define __NR_getgid32		200
 #define __NR_geteuid32		201
@@ -217,15 +217,18 @@
 #define __NR_getresuid32	209
 #define __NR_setresgid32	210
 #define __NR_getresgid32	211
-#define __NR_lchown32		212
+#define __NR_chown32		212
 #define __NR_setuid32		213
 #define __NR_setgid32		214
 #define __NR_setfsuid32		215
 #define __NR_setfsgid32		216
 #define __NR_pivot_root		217
+#define __NR_mincore		218
+#define __NR_madvise		219
+#define __NR_madvise1		219
 #define __NR_getdents64		220
 #define __NR_fcntl64		221
-#define __NR_security		223
+/* 223 is unused */
 #define __NR_gettid		224
 #define __NR_readahead		225
 #define __NR_setxattr		226
@@ -252,13 +255,13 @@
 #define __NR_io_getevents	247
 #define __NR_io_submit		248
 #define __NR_io_cancel		249
-#define __NR_alloc_hugepages	250
-#define __NR_free_hugepages	251
+#define __NR_fadvise64		250
+/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */
 #define __NR_exit_group		252
 #define __NR_lookup_dcookie	253
-#define __NR_sys_epoll_create	254
-#define __NR_sys_epoll_ctl	255
-#define __NR_sys_epoll_wait	256
+#define __NR_epoll_create	254
+#define __NR_epoll_ctl		255
+#define __NR_epoll_wait		256
 #define __NR_remap_file_pages	257
 #define __NR_set_tid_address	258
 #define __NR_timer_create	259
@@ -291,10 +294,41 @@
 #define __NR_add_key		286
 #define __NR_request_key	287
 #define __NR_keyctl		288
+#define __NR_ioprio_set		289
+#define __NR_ioprio_get		290
+#define __NR_inotify_init	291
+#define __NR_inotify_add_watch	292
+#define __NR_inotify_rm_watch	293
+#define __NR_migrate_pages	294
+#define __NR_openat		295
+#define __NR_mkdirat		296
+#define __NR_mknodat		297
+#define __NR_fchownat		298
+#define __NR_futimesat		299
+#define __NR_fstatat64		300
+#define __NR_unlinkat		301
+#define __NR_renameat		302
+#define __NR_linkat		303
+#define __NR_symlinkat		304
+#define __NR_readlinkat		305
+#define __NR_fchmodat		306
+#define __NR_faccessat		307
+#define __NR_pselect6		308
+#define __NR_ppoll		309
+#define __NR_unshare		310
+#define __NR_set_robust_list	311
+#define __NR_get_robust_list	312
+#define __NR_splice		313
+#define __NR_sync_file_range	314
+#define __NR_tee		315
+#define __NR_vmsplice		316
+#define __NR_move_pages		317
+#define __NR_getcpu		318
+#define __NR_epoll_pwait	319
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 289
+#define NR_syscalls 320
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h
index 0f70b37..eb7da54 100644
--- a/include/asm-i386/alternative.h
+++ b/include/asm-i386/alternative.h
@@ -98,6 +98,12 @@
 		      ".previous" : output : [feat] "i" (feature), ##input)
 
 /*
+ * use this macro(s) if you need more than one output parameter
+ * in alternative_io
+ */
+#define ASM_OUTPUT2(a, b) a, b
+
+/*
  * Alternative inline assembly for SMP.
  *
  * The LOCK_PREFIX macro defined here replaces the LOCK and
diff --git a/include/asm-i386/paravirt.h b/include/asm-i386/paravirt.h
index bc5c12c..d7a0512 100644
--- a/include/asm-i386/paravirt.h
+++ b/include/asm-i386/paravirt.h
@@ -222,11 +222,6 @@
 	void (*iret)(void);
 };
 
-/* Mark a paravirt probe function. */
-#define paravirt_probe(fn)						\
- static asmlinkage void (*__paravirtprobe_##fn)(void) __attribute_used__ \
-		__attribute__((__section__(".paravirtprobe"))) = fn
-
 extern struct paravirt_ops paravirt_ops;
 
 #define PARAVIRT_PATCH(x)					\
diff --git a/include/asm-i386/poll.h b/include/asm-i386/poll.h
index 2cd4929..c98509d 100644
--- a/include/asm-i386/poll.h
+++ b/include/asm-i386/poll.h
@@ -1,27 +1 @@
-#ifndef __i386_POLL_H
-#define __i386_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-i386/tsc.h b/include/asm-i386/tsc.h
index 3f3c1fa..62c091f 100644
--- a/include/asm-i386/tsc.h
+++ b/include/asm-i386/tsc.h
@@ -35,14 +35,16 @@
 static __always_inline cycles_t get_cycles_sync(void)
 {
 	unsigned long long ret;
-	unsigned eax;
+	unsigned eax, edx;
 
 	/*
   	 * Use RDTSCP if possible; it is guaranteed to be synchronous
  	 * and doesn't cause a VMEXIT on Hypervisors
 	 */
 	alternative_io(ASM_NOP3, ".byte 0x0f,0x01,0xf9", X86_FEATURE_RDTSCP,
-			 	 "=A" (ret), "0" (0ULL) : "ecx", "memory");
+		       ASM_OUTPUT2("=a" (eax), "=d" (edx)),
+		       "a" (0U), "d" (0U) : "ecx", "memory");
+	ret = (((unsigned long long)edx) << 32) | ((unsigned long long)eax);
 	if (ret)
 		return ret;
 
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index bd21e79..e84ace1 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -326,10 +326,13 @@
 #define __NR_getcpu		318
 #define __NR_epoll_pwait	319
 #define __NR_utimensat		320
+#define __NR_signalfd		321
+#define __NR_timerfd		322
+#define __NR_eventfd		323
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 321
+#define NR_syscalls 324
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-ia64/poll.h b/include/asm-ia64/poll.h
index bcaf9f1..c98509d 100644
--- a/include/asm-ia64/poll.h
+++ b/include/asm-ia64/poll.h
@@ -1,32 +1 @@
-#ifndef _ASM_IA64_POLL_H
-#define _ASM_IA64_POLL_H
-
-/*
- * poll(2) bit definitions.  Based on <asm-i386/poll.h>.
- *
- * Modified 1998, 1999, 2002
- *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
- */
-
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif /* _ASM_IA64_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
index 7509257..bca3475 100644
--- a/include/asm-m32r/pgtable-2level.h
+++ b/include/asm-m32r/pgtable-2level.h
@@ -71,8 +71,8 @@
 #define pfn_pmd(pfn, prot)	__pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
 #define PTE_FILE_MAX_BITS	29
-#define pte_to_pgoff(pte)	(((pte_val(pte) >> 2) & 0xef) | (((pte_val(pte) >> 10)) << 7))
-#define pgoff_to_pte(off)	((pte_t) { (((off) & 0xef) << 2) | (((off) >> 7) << 10) | _PAGE_FILE })
+#define pte_to_pgoff(pte)	(((pte_val(pte) >> 2) & 0x7f) | (((pte_val(pte) >> 10)) << 7))
+#define pgoff_to_pte(off)	((pte_t) { (((off) & 0x7f) << 2) | (((off) >> 7) << 10) | _PAGE_FILE })
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_M32R_PGTABLE_2LEVEL_H */
diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
index 8b2a2f1..6604303 100644
--- a/include/asm-m32r/pgtable.h
+++ b/include/asm-m32r/pgtable.h
@@ -366,7 +366,7 @@
 #define pte_unmap_nested(pte)	do { } while (0)
 
 /* Encode and de-code a swap entry */
-#define __swp_type(x)			(((x).val >> 2) & 0x3f)
+#define __swp_type(x)			(((x).val >> 2) & 0x1f)
 #define __swp_offset(x)			((x).val >> 10)
 #define __swp_entry(type, offset)	\
 	((swp_entry_t) { ((type) << 2) | ((offset) << 10) })
diff --git a/include/asm-m32r/poll.h b/include/asm-m32r/poll.h
index 9e0e700..c98509d 100644
--- a/include/asm-m32r/poll.h
+++ b/include/asm-m32r/poll.h
@@ -1,32 +1 @@
-#ifndef _ASM_M32R_POLL_H
-#define _ASM_M32R_POLL_H
-
-/*
- * poll(2) bit definitions.  Based on <asm-i386/poll.h>.
- *
- * Modified 2004
- *      Hirokazu Takata <takata at linux-m32r.org>
- */
-
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif  /* _ASM_M32R_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-m32r/system.h b/include/asm-m32r/system.h
index f62f5c9..b291b2f 100644
--- a/include/asm-m32r/system.h
+++ b/include/asm-m32r/system.h
@@ -21,12 +21,22 @@
  * `next' and `prev' should be struct task_struct, but it isn't always defined
  */
 
+#if defined(CONFIG_FRAME_POINTER) || \
+	!defined(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER)
+#define M32R_PUSH_FP "	push fp\n"
+#define M32R_POP_FP  "	pop  fp\n"
+#else
+#define M32R_PUSH_FP ""
+#define M32R_POP_FP  ""
+#endif
+
 #define switch_to(prev, next, last)  do { \
 	__asm__ __volatile__ ( \
 		"	seth	lr, #high(1f)				\n" \
 		"	or3	lr, lr, #low(1f)			\n" \
 		"	st	lr, @%4  ; store old LR			\n" \
 		"	ld	lr, @%5  ; load new LR			\n" \
+			M32R_PUSH_FP \
 		"	st	sp, @%2  ; store old SP			\n" \
 		"	ld	sp, @%3  ; load new SP			\n" \
 		"	push	%1  ; store `prev' on new stack		\n" \
@@ -34,6 +44,7 @@
 		"	.fillinsn					\n" \
 		"1:							\n" \
 		"	pop	%0  ; restore `__last' from new stack	\n" \
+			M32R_POP_FP \
 		: "=r" (last) \
 		: "0" (prev), \
 		  "r" (&(prev->thread.sp)), "r" (&(next->thread.sp)), \
diff --git a/include/asm-m68k/atarihw.h b/include/asm-m68k/atarihw.h
index 6211363..ecf007d 100644
--- a/include/asm-m68k/atarihw.h
+++ b/include/asm-m68k/atarihw.h
@@ -2,7 +2,7 @@
 ** linux/atarihw.h -- This header defines some macros and pointers for
 **                    the various Atari custom hardware registers.
 **
-** Copyright 1994 by Bj”rn Brauel
+** Copyright 1994 by Björn Brauel
 **
 ** 5/1/94 Roman Hodek:
 **   Added definitions for TT specific chips.
diff --git a/include/asm-m68k/atariints.h b/include/asm-m68k/atariints.h
index ce6c445..5748e99 100644
--- a/include/asm-m68k/atariints.h
+++ b/include/asm-m68k/atariints.h
@@ -1,7 +1,7 @@
 /*
 ** atariints.h -- Atari Linux interrupt handling structs and prototypes
 **
-** Copyright 1994 by Bj”rn Brauel
+** Copyright 1994 by Björn Brauel
 **
 ** 5/2/94 Roman Hodek:
 **   TT interrupt definitions added.
diff --git a/include/asm-m68k/poll.h b/include/asm-m68k/poll.h
index 0fb8843..f080fcd 100644
--- a/include/asm-m68k/poll.h
+++ b/include/asm-m68k/poll.h
@@ -1,24 +1,9 @@
 #ifndef __m68k_POLL_H
 #define __m68k_POLL_H
 
-#define POLLIN		  1
-#define POLLPRI		  2
-#define POLLOUT		  4
-#define POLLERR		  8
-#define POLLHUP		 16
-#define POLLNVAL	 32
-#define POLLRDNORM	 64
 #define POLLWRNORM	POLLOUT
-#define POLLRDBAND	128
 #define POLLWRBAND	256
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
 
 #endif
diff --git a/include/asm-mips/atomic.h b/include/asm-mips/atomic.h
index 62daa74..1b60624 100644
--- a/include/asm-mips/atomic.h
+++ b/include/asm-mips/atomic.h
@@ -689,7 +689,7 @@
 }
 
 #define atomic64_cmpxchg(v, o, n) \
-	(((__typeof__((v)->counter)))cmpxchg(&((v)->counter), (o), (n)))
+	((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n)))
 #define atomic64_xchg(v, new) (xchg(&((v)->counter), (new)))
 
 /**
diff --git a/include/asm-mips/bootinfo.h b/include/asm-mips/bootinfo.h
index dbf834f..b0c3297 100644
--- a/include/asm-mips/bootinfo.h
+++ b/include/asm-mips/bootinfo.h
@@ -119,9 +119,9 @@
  */
 #define MACH_GROUP_MOMENCO	12	/* Momentum Boards		*/
 #define  MACH_MOMENCO_OCELOT	0
-#define  MACH_MOMENCO_OCELOT_G	1
+#define  MACH_MOMENCO_OCELOT_G	1	/* no more supported (may 2007) */
 #define  MACH_MOMENCO_OCELOT_C	2
-#define  MACH_MOMENCO_JAGUAR_ATX 3
+#define  MACH_MOMENCO_JAGUAR_ATX 3	/* no more supported (may 2007) */
 #define  MACH_MOMENCO_OCELOT_3	4
 
 /*
diff --git a/include/asm-mips/fpu.h b/include/asm-mips/fpu.h
index b414a7d..483685b 100644
--- a/include/asm-mips/fpu.h
+++ b/include/asm-mips/fpu.h
@@ -16,6 +16,7 @@
 #include <asm/mipsregs.h>
 #include <asm/cpu.h>
 #include <asm/cpu-features.h>
+#include <asm/hazards.h>
 #include <asm/bitops.h>
 #include <asm/processor.h>
 #include <asm/current.h>
@@ -38,34 +39,16 @@
 extern void _save_fp(struct task_struct *);
 extern void _restore_fp(struct task_struct *);
 
-#if defined(CONFIG_CPU_SB1)
-#define __enable_fpu_hazard()						\
-do {									\
-	asm(".set	push		\n\t"				\
-	    ".set	mips64		\n\t"				\
-	    ".set	noreorder	\n\t"				\
-	    "ssnop			\n\t"				\
-	    "bnezl	$0, .+4		\n\t"				\
-	    "ssnop			\n\t"				\
-	    ".set pop");						\
-} while (0)
-#else
-#define __enable_fpu_hazard()						\
-do {									\
-	asm("nop;nop;nop;nop");		/* max. hazard */		\
-} while (0)
-#endif
-
 #define __enable_fpu()							\
 do {									\
         set_c0_status(ST0_CU1);						\
-        __enable_fpu_hazard();						\
+        enable_fpu_hazard();						\
 } while (0)
 
 #define __disable_fpu()							\
 do {									\
 	clear_c0_status(ST0_CU1);					\
-	/* We don't care about the c0 hazard here  */			\
+        disable_fpu_hazard();						\
 } while (0)
 
 #define enable_fpu()							\
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index e50c77e..d9119f4 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -178,4 +178,36 @@
 
 #endif
 
+
+/* FPU hazards */
+
+#if defined(CONFIG_CPU_SB1)
+ASMMACRO(enable_fpu_hazard,
+	 .set	push;
+	 .set	mips64;
+	 .set	noreorder;
+	 _ssnop;
+	 bnezl	$0,.+4;
+	 _ssnop;
+	 .set	pop
+)
+ASMMACRO(disable_fpu_hazard,
+)
+
+#elif defined(CONFIG_CPU_MIPSR2)
+ASMMACRO(enable_fpu_hazard,
+	 _ehb
+)
+ASMMACRO(disable_fpu_hazard,
+	 _ehb
+)
+#else
+ASMMACRO(enable_fpu_hazard,
+	 nop; nop; nop; nop
+)
+ASMMACRO(disable_fpu_hazard,
+	 _ehb
+)
+#endif
+
 #endif /* _ASM_HAZARDS_H */
diff --git a/include/asm-mips/highmem.h b/include/asm-mips/highmem.h
index f8c8182..4d6bd5c 100644
--- a/include/asm-mips/highmem.h
+++ b/include/asm-mips/highmem.h
@@ -48,46 +48,6 @@
 extern void * kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
 
-/*
- * CONFIG_LIMITED_DMA is for systems with DMA limitations such as Momentum's
- * Jaguar ATX.  This option exploits the highmem code in the kernel so is
- * always enabled together with CONFIG_HIGHMEM but at this time doesn't
- * actually add highmem functionality.
- */
-
-#ifdef CONFIG_LIMITED_DMA
-
-/*
- * These are the default functions for the no-highmem case from
- * <linux/highmem.h>
- */
-static inline void *kmap(struct page *page)
-{
-	might_sleep();
-	return page_address(page);
-}
-
-#define kunmap(page) do { (void) (page); } while (0)
-
-static inline void *kmap_atomic(struct page *page, enum km_type type)
-{
-	pagefault_disable();
-	return page_address(page);
-}
-
-static inline void kunmap_atomic(void *kvaddr, enum km_type type)
-{
-	pagefault_enable();
-}
-
-#define kmap_atomic_pfn(pfn, idx) kmap_atomic(pfn_to_page(pfn), (idx))
-
-#define kmap_atomic_to_page(ptr) virt_to_page(ptr)
-
-#define flush_cache_kmaps()	do { } while (0)
-
-#else /* LIMITED_DMA */
-
 extern void *__kmap(struct page *page);
 extern void __kunmap(struct page *page);
 extern void *__kmap_atomic(struct page *page, enum km_type type);
@@ -103,8 +63,6 @@
 
 #define flush_cache_kmaps()	flush_cache_all()
 
-#endif /* LIMITED_DMA */
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_HIGHMEM_H */
diff --git a/include/asm-mips/mach-cobalt/cobalt.h b/include/asm-mips/mach-cobalt/cobalt.h
index 24a8d51..684a501 100644
--- a/include/asm-mips/mach-cobalt/cobalt.h
+++ b/include/asm-mips/mach-cobalt/cobalt.h
@@ -69,6 +69,8 @@
 #define COBALT_BRD_ID_QUBE2    0x5
 #define COBALT_BRD_ID_RAQ2     0x6
 
+extern int cobalt_board_id;
+
 #define PCI_CFG_SET(devfn,where)					\
 	GT_WRITE(GT_PCI0_CFGADDR_OFS, (0x80000000 | (PCI_SLOT (devfn) << 11) |		\
 		(PCI_FUNC (devfn) << 8) | (where)))
diff --git a/include/asm-mips/mach-ja/cpu-feature-overrides.h b/include/asm-mips/mach-ja/cpu-feature-overrides.h
deleted file mode 100644
index 84b6dea..0000000
--- a/include/asm-mips/mach-ja/cpu-feature-overrides.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003, 2004 Ralf Baechle
- */
-#ifndef __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-#define __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H
-
-/*
- * Momentum Jaguar ATX always has the RM9000 processor.
- */
-#define cpu_has_watch		1
-#define cpu_has_mips16		0
-#define cpu_has_divec		0
-#define cpu_has_vce		0
-#define cpu_has_cache_cdex_p	0
-#define cpu_has_cache_cdex_s	0
-#define cpu_has_prefetch	1
-#define cpu_has_mcheck		0
-#define cpu_has_ejtag		0
-
-#define cpu_has_llsc		1
-#define cpu_has_vtag_icache	0
-#define cpu_has_dc_aliases	0
-#define cpu_has_ic_fills_f_dc	0
-#define cpu_has_dsp		0
-#define cpu_icache_snoops_remote_store	0
-
-#define cpu_has_nofpuex		0
-#define cpu_has_64bits		1
-
-#define cpu_has_inclusive_pcaches	0
-
-#define cpu_dcache_line_size()	32
-#define cpu_icache_line_size()	32
-#define cpu_scache_line_size()	32
-
-#define cpu_has_mips32r1	0
-#define cpu_has_mips32r2	0
-#define cpu_has_mips64r1	0
-#define cpu_has_mips64r2	0
-
-#endif /* __ASM_MACH_JA_CPU_FEATURE_OVERRIDES_H */
diff --git a/include/asm-mips/mach-ja/spaces.h b/include/asm-mips/mach-ja/spaces.h
deleted file mode 100644
index 8466a0e..0000000
--- a/include/asm-mips/mach-ja/spaces.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle
- * Copyright (C) 2000, 2002  Maciej W. Rozycki
- * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc.
- */
-#ifndef __ASM_MACH_JA_SPACES_H
-#define __ASM_MACH_JA_SPACES_H
-
-/*
- * Memory above this physical address will be considered highmem.
- */
-#define HIGHMEM_START		0x08000000UL
-
-#include_next <spaces.h>
-
-#endif /* __ASM_MACH_JA_SPACES_H */
diff --git a/include/asm-mips/mips-boards/malta.h b/include/asm-mips/mips-boards/malta.h
index b0ba3c5..eec9100 100644
--- a/include/asm-mips/mips-boards/malta.h
+++ b/include/asm-mips/mips-boards/malta.h
@@ -25,6 +25,10 @@
 #include <asm/mips-boards/msc01_pci.h>
 #include <asm/gt64120.h>
 
+/* Mips interrupt controller found in SOCit variations */
+#define MIPS_MSC01_IC_REG_BASE		0x1bc40000
+#define MIPS_SOCITSC_IC_REG_BASE	0x1ffa0000
+
 /*
  * Malta I/O ports base address for the Galileo GT64120 and Algorithmics
  * Bonito system controllers.
diff --git a/include/asm-mips/msc01_ic.h b/include/asm-mips/msc01_ic.h
index aa7ad9a..7989b9f 100644
--- a/include/asm-mips/msc01_ic.h
+++ b/include/asm-mips/msc01_ic.h
@@ -94,10 +94,7 @@
 /*
  * MIPS System controller interrupt register base.
  *
- * FIXME - are these macros specific to Malta and co or to the MSC?  If the
- * latter, they should be moved elsewhere.
  */
-#define MIPS_MSC01_IC_REG_BASE	0x1bc40000
 
 /*****************************************************************************
  * Absolute register addresses
@@ -144,7 +141,7 @@
 #define MSC01_IRQ_LEVEL		0
 #define MSC01_IRQ_EDGE		1
 
-extern void __init init_msc_irqs(unsigned int base, msc_irqmap_t *imp, int nirq);
+extern void __init init_msc_irqs(unsigned long icubase, unsigned int base, msc_irqmap_t *imp, int nirq);
 extern void ll_msc_irq(void);
 
 #endif /* __ASM_MIPS_BOARDS_MSC01_IC_H */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index d3fbd83..5c3239d 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -190,10 +190,6 @@
 #define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
 #define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
 
-#ifdef CONFIG_LIMITED_DMA
-#define WANT_PAGE_VIRTUAL
-#endif
-
 #include <asm-generic/memory_model.h>
 #include <asm-generic/page.h>
 
diff --git a/include/asm-mips/poll.h b/include/asm-mips/poll.h
index 70881f8..47b9520 100644
--- a/include/asm-mips/poll.h
+++ b/include/asm-mips/poll.h
@@ -1,28 +1,9 @@
 #ifndef __ASM_POLL_H
 #define __ASM_POLL_H
 
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
 #define POLLWRNORM	POLLOUT
 #define POLLWRBAND	0x0100
 
-/* These seem to be more or less nonstandard ...  */
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
 
 #endif /* __ASM_POLL_H */
diff --git a/include/asm-mips/serial.h b/include/asm-mips/serial.h
index d7a6513..ce51213 100644
--- a/include/asm-mips/serial.h
+++ b/include/asm-mips/serial.h
@@ -81,25 +81,6 @@
 #define STD_SERIAL_PORT_DEFNS
 #endif /* CONFIG_HAVE_STD_PC_SERIAL_PORTS */
 
-#ifdef CONFIG_MOMENCO_JAGUAR_ATX
-/* Ordinary NS16552 duart with a 20MHz crystal.  */
-#define JAGUAR_ATX_UART_CLK	20000000
-#define JAGUAR_ATX_BASE_BAUD	(JAGUAR_ATX_UART_CLK / 16)
-
-#define JAGUAR_ATX_SERIAL1_IRQ	6
-#define JAGUAR_ATX_SERIAL1_BASE	0xfd000023L
-
-#define _JAGUAR_ATX_SERIAL_INIT(int, base)				\
-	{ .baud_base = JAGUAR_ATX_BASE_BAUD, irq: int,			\
-	  .flags = (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST),		\
-	  .iomem_base = (u8 *) base, iomem_reg_shift: 2,			\
-	  io_type: SERIAL_IO_MEM }
-#define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS				\
-	_JAGUAR_ATX_SERIAL_INIT(JAGUAR_ATX_SERIAL1_IRQ, JAGUAR_ATX_SERIAL1_BASE)
-#else
-#define MOMENCO_JAGUAR_ATX_SERIAL_PORT_DEFNS
-#endif
-
 #ifdef CONFIG_MOMENCO_OCELOT_3
 #define OCELOT_3_BASE_BAUD	( 20000000 / 16 )
 #define OCELOT_3_SERIAL_IRQ	6
@@ -134,27 +115,6 @@
 #define MOMENCO_OCELOT_SERIAL_PORT_DEFNS
 #endif
 
-#ifdef CONFIG_MOMENCO_OCELOT_G
-/* Ordinary NS16552 duart with a 20MHz crystal.  */
-#define OCELOT_G_BASE_BAUD ( 20000000 / 16 )
-
-#define OCELOT_G_SERIAL1_IRQ	4
-#if 0
-#define OCELOT_G_SERIAL1_BASE	0xe0001020
-#else
-#define OCELOT_G_SERIAL1_BASE	0xfd000020
-#endif
-
-#define _OCELOT_G_SERIAL_INIT(int, base)				\
-	{ .baud_base = OCELOT_G_BASE_BAUD, .irq = int, .flags = STD_COM_FLAGS,\
-	  .iomem_base = (u8 *) base, .iomem_reg_shift = 2,			\
-	  .io_type = SERIAL_IO_MEM }
-#define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS				\
-	_OCELOT_G_SERIAL_INIT(OCELOT_G_SERIAL1_IRQ, OCELOT_G_SERIAL1_BASE)
-#else
-#define MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS
-#endif
-
 #ifdef CONFIG_MOMENCO_OCELOT_C
 /* Ordinary NS16552 duart with a 20MHz crystal.  */
 #define OCELOT_C_BASE_BAUD ( 20000000 / 16 )
@@ -210,7 +170,6 @@
 	IP32_SERIAL_PORT_DEFNS                          \
 	JAZZ_SERIAL_PORT_DEFNS				\
 	STD_SERIAL_PORT_DEFNS				\
-	MOMENCO_OCELOT_G_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_C_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_SERIAL_PORT_DEFNS		\
 	MOMENCO_OCELOT_3_SERIAL_PORT_DEFNS
diff --git a/include/asm-mips/sgi/seeq.h b/include/asm-mips/sgi/seeq.h
new file mode 100644
index 0000000..af0ffd7
--- /dev/null
+++ b/include/asm-mips/sgi/seeq.h
@@ -0,0 +1,21 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Ralf Baechle
+ */
+#ifndef __ASM_SGI_SEEQ_H
+#define __ASM_SGI_SEEQ_H
+
+#include <linux/if_ether.h>
+
+#include <asm/sgi/hpc3.h>
+
+struct sgiseeq_platform_data {
+	struct hpc3_regs *hpc;
+	unsigned int irq;
+	unsigned char mac[ETH_ALEN];
+};
+
+#endif /* __ASM_SGI_SEEQ_H */
diff --git a/include/asm-mips/sgi/wd.h b/include/asm-mips/sgi/wd.h
new file mode 100644
index 0000000..0d6c3a4
--- /dev/null
+++ b/include/asm-mips/sgi/wd.h
@@ -0,0 +1,20 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2007 by Ralf Baechle
+ */
+#ifndef __ASM_SGI_WD_H
+#define __ASM_SGI_WD_H
+
+#include <asm/sgi/hpc3.h>
+
+struct sgiwd93_platform_data {
+	unsigned int unit;
+	unsigned int irq;
+	struct hpc3_scsiregs *hregs;
+	unsigned char *wdregs;
+};
+
+#endif /* __ASM_SGI_WD_H */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 3713d25..bb0b289 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -464,7 +464,10 @@
 
 extern void set_handler (unsigned long offset, void *addr, unsigned long len);
 extern void set_uncached_handler (unsigned long offset, void *addr, unsigned long len);
-extern void *set_vi_handler (int n, void *addr);
+
+typedef void (*vi_handler_t)(void);
+extern void *set_vi_handler (int n, vi_handler_t addr);
+
 extern void *set_except_vector(int n, void *addr);
 extern unsigned long ebase;
 extern void per_cpu_trap_init(void);
diff --git a/include/asm-parisc/poll.h b/include/asm-parisc/poll.h
index 20e4d03..c98509d 100644
--- a/include/asm-parisc/poll.h
+++ b/include/asm-parisc/poll.h
@@ -1,27 +1 @@
-#ifndef __PARISC_POLL_H
-#define __PARISC_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-powerpc/hw_irq.h b/include/asm-powerpc/hw_irq.h
index 9e4dd98..a7b60bf 100644
--- a/include/asm-powerpc/hw_irq.h
+++ b/include/asm-powerpc/hw_irq.h
@@ -48,8 +48,15 @@
 
 #define irqs_disabled()		(local_get_flags() == 0)
 
-#define hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
-#define hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
+#define __hard_irq_enable()	__mtmsrd(mfmsr() | MSR_EE, 1)
+#define __hard_irq_disable()	__mtmsrd(mfmsr() & ~MSR_EE, 1)
+
+#define  hard_irq_disable()			\
+	do {					\
+		__hard_irq_disable();		\
+		get_paca()->soft_enabled = 0;	\
+		get_paca()->hard_enabled = 0;	\
+	} while(0)
 
 #else
 
diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
index e2ca55b..b8dca30 100644
--- a/include/asm-powerpc/mmu-hash64.h
+++ b/include/asm-powerpc/mmu-hash64.h
@@ -73,8 +73,9 @@
 
 #define HPTES_PER_GROUP 8
 
+#define HPTE_V_SSIZE_SHIFT	62
 #define HPTE_V_AVPN_SHIFT	7
-#define HPTE_V_AVPN		ASM_CONST(0xffffffffffffff80)
+#define HPTE_V_AVPN		ASM_CONST(0x3fffffffffffff80)
 #define HPTE_V_AVPN_VAL(x)	(((x) & HPTE_V_AVPN) >> HPTE_V_AVPN_SHIFT)
 #define HPTE_V_COMPARE(x,y)	(!(((x) ^ (y)) & HPTE_V_AVPN))
 #define HPTE_V_BOLTED		ASM_CONST(0x0000000000000010)
@@ -151,6 +152,15 @@
 #define MMU_PAGE_16G		5	/* 16G */
 #define MMU_PAGE_COUNT		6
 
+/*
+ * Segment sizes.
+ * These are the values used by hardware in the B field of
+ * SLB entries and the first dword of MMU hashtable entries.
+ * The B field is 2 bits; the values 2 and 3 are unused and reserved.
+ */
+#define MMU_SEGSIZE_256M	0
+#define MMU_SEGSIZE_1T		1
+
 #ifndef __ASSEMBLY__
 
 /*
diff --git a/include/asm-powerpc/mmzone.h b/include/asm-powerpc/mmzone.h
index d484ca9..19f299b 100644
--- a/include/asm-powerpc/mmzone.h
+++ b/include/asm-powerpc/mmzone.h
@@ -43,9 +43,5 @@
 
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
 
-#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
-extern int __init early_pfn_to_nid(unsigned long pfn);
-#endif
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-powerpc/poll.h b/include/asm-powerpc/poll.h
index 9c7d126..c98509d 100644
--- a/include/asm-powerpc/poll.h
+++ b/include/asm-powerpc/poll.h
@@ -1,24 +1 @@
-#ifndef _ASM_POWERPC_POLL_H
-#define _ASM_POWERPC_POLL_H
-
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif	/* _ASM_POWERPC_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-powerpc/ppc-pci.h b/include/asm-powerpc/ppc-pci.h
index 6dcd7a8..8e20051 100644
--- a/include/asm-powerpc/ppc-pci.h
+++ b/include/asm-powerpc/ppc-pci.h
@@ -62,11 +62,14 @@
 
 /**
  * eeh_slot_error_detail -- record and EEH error condition to the log
- * @severity: 1 if temporary, 2 if permanent failure.
+ * @pdn:      pci device node
+ * @severity: EEH_LOG_TEMP_FAILURE or EEH_LOG_PERM_FAILURE
  *
  * Obtains the EEH error details from the RTAS subsystem,
  * and then logs these details with the RTAS error log system.
  */
+#define EEH_LOG_TEMP_FAILURE 1
+#define EEH_LOG_PERM_FAILURE 2
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
 
 /**
@@ -82,6 +85,7 @@
 
 /**
  * rtas_set_slot_reset -- unfreeze a frozen slot
+ * @pdn:       pci device node
  *
  * Clear the EEH-frozen condition on a slot.  This routine
  * does this by asserting the PCI #RST line for 1/8th of
@@ -95,6 +99,7 @@
 
 /** 
  * eeh_restore_bars - Restore device configuration info.
+ * @pdn:       pci device node
  *
  * A reset of a PCI device will clear out its config space.
  * This routines will restore the config space for this
@@ -105,6 +110,7 @@
 
 /**
  * rtas_configure_bridge -- firmware initialization of pci bridge
+ * @pdn:       pci device node
  *
  * Ask the firmware to configure all PCI bridges devices
  * located behind the indicated node. Required after a
@@ -118,16 +124,22 @@
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 
 /**
+ * eeh_mark_slot -- set mode flags for pertition endpoint
+ * @pdn:       pci device node
+ *
  * mark and clear slots: find "partition endpoint" PE and set or 
  * clear the flags for each subnode of the PE.
  */
 void eeh_mark_slot (struct device_node *dn, int mode_flag);
 void eeh_clear_slot (struct device_node *dn, int mode_flag);
 
-/* Find the associated "Partiationable Endpoint" PE */
+/**
+ * find_device_pe -- Find the associated "Partiationable Endpoint" PE
+ * @pdn:       pci device node
+ */
 struct device_node * find_device_pe(struct device_node *dn);
 
-#endif
+#endif /* CONFIG_EEH */
 
 #else /* CONFIG_PCI */
 static inline void find_and_init_phbs(void) { }
diff --git a/include/asm-powerpc/ps3.h b/include/asm-powerpc/ps3.h
index 13c372d..1e04651 100644
--- a/include/asm-powerpc/ps3.h
+++ b/include/asm-powerpc/ps3.h
@@ -377,8 +377,13 @@
 
 /* system manager */
 
+#ifdef CONFIG_PS3_SYS_MANAGER
 void ps3_sys_manager_restart(void);
 void ps3_sys_manager_power_off(void);
+#else
+static inline void ps3_sys_manager_restart(void) {}
+static inline void ps3_sys_manager_power_off(void) {}
+#endif
 
 struct ps3_prealloc {
     const char *name;
diff --git a/include/asm-powerpc/qe.h b/include/asm-powerpc/qe.h
index a62168ec..9d304b1 100644
--- a/include/asm-powerpc/qe.h
+++ b/include/asm-powerpc/qe.h
@@ -38,11 +38,11 @@
 void qe_setbrg(u32 brg, u32 rate);
 int qe_get_snum(void);
 void qe_put_snum(u8 snum);
-u32 qe_muram_alloc(u32 size, u32 align);
-int qe_muram_free(u32 offset);
-u32 qe_muram_alloc_fixed(u32 offset, u32 size);
+unsigned long qe_muram_alloc(int size, int align);
+int qe_muram_free(unsigned long offset);
+unsigned long qe_muram_alloc_fixed(unsigned long offset, int size);
 void qe_muram_dump(void);
-void *qe_muram_addr(u32 offset);
+void *qe_muram_addr(unsigned long offset);
 
 /* Buffer descriptors */
 struct qe_bd {
@@ -448,10 +448,5 @@
 #define UCC_FAST_FUNCTION_CODE_DTB_LCL	0x02
 #define UCC_FAST_FUNCTION_CODE_BDB_LCL	0x01
 
-static inline long IS_MURAM_ERR(const u32 offset)
-{
-	return offset > (u32) - 1000L;
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_QE_H */
diff --git a/include/asm-powerpc/reg_booke.h b/include/asm-powerpc/reg_booke.h
new file mode 100644
index 0000000..064405c
--- /dev/null
+++ b/include/asm-powerpc/reg_booke.h
@@ -0,0 +1,469 @@
+/*
+ * Contains register definitions common to the Book E PowerPC
+ * specification.  Notice that while the IBM-40x series of CPUs
+ * are not true Book E PowerPCs, they borrowed a number of features
+ * before Book E was finalized, and are included here as well.  Unfortunatly,
+ * they sometimes used different locations than true Book E CPUs did.
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_POWERPC_REG_BOOKE_H__
+#define __ASM_POWERPC_REG_BOOKE_H__
+
+#ifndef __ASSEMBLY__
+/* Performance Monitor Registers */
+#define mfpmr(rn)	({unsigned int rval; \
+			asm volatile("mfpmr %0," __stringify(rn) \
+				     : "=r" (rval)); rval;})
+#define mtpmr(rn, v)	asm volatile("mtpmr " __stringify(rn) ",%0" : : "r" (v))
+#endif /* __ASSEMBLY__ */
+
+/* Freescale Book E Performance Monitor APU Registers */
+#define PMRN_PMC0	0x010	/* Performance Monitor Counter 0 */
+#define PMRN_PMC1	0x011	/* Performance Monitor Counter 1 */
+#define PMRN_PMC2	0x012	/* Performance Monitor Counter 1 */
+#define PMRN_PMC3	0x013	/* Performance Monitor Counter 1 */
+#define PMRN_PMLCA0	0x090	/* PM Local Control A0 */
+#define PMRN_PMLCA1	0x091	/* PM Local Control A1 */
+#define PMRN_PMLCA2	0x092	/* PM Local Control A2 */
+#define PMRN_PMLCA3	0x093	/* PM Local Control A3 */
+
+#define PMLCA_FC	0x80000000	/* Freeze Counter */
+#define PMLCA_FCS	0x40000000	/* Freeze in Supervisor */
+#define PMLCA_FCU	0x20000000	/* Freeze in User */
+#define PMLCA_FCM1	0x10000000	/* Freeze when PMM==1 */
+#define PMLCA_FCM0	0x08000000	/* Freeze when PMM==0 */
+#define PMLCA_CE	0x04000000	/* Condition Enable */
+
+#define PMLCA_EVENT_MASK 0x007f0000	/* Event field */
+#define PMLCA_EVENT_SHIFT	16
+
+#define PMRN_PMLCB0	0x110	/* PM Local Control B0 */
+#define PMRN_PMLCB1	0x111	/* PM Local Control B1 */
+#define PMRN_PMLCB2	0x112	/* PM Local Control B2 */
+#define PMRN_PMLCB3	0x113	/* PM Local Control B3 */
+
+#define PMLCB_THRESHMUL_MASK	0x0700	/* Threshhold Multiple Field */
+#define PMLCB_THRESHMUL_SHIFT	8
+
+#define PMLCB_THRESHOLD_MASK	0x003f	/* Threshold Field */
+#define PMLCB_THRESHOLD_SHIFT	0
+
+#define PMRN_PMGC0	0x190	/* PM Global Control 0 */
+
+#define PMGC0_FAC	0x80000000	/* Freeze all Counters */
+#define PMGC0_PMIE	0x40000000	/* Interrupt Enable */
+#define PMGC0_FCECE	0x20000000	/* Freeze countes on
+					   Enabled Condition or
+					   Event */
+
+#define PMRN_UPMC0	0x000	/* User Performance Monitor Counter 0 */
+#define PMRN_UPMC1	0x001	/* User Performance Monitor Counter 1 */
+#define PMRN_UPMC2	0x002	/* User Performance Monitor Counter 1 */
+#define PMRN_UPMC3	0x003	/* User Performance Monitor Counter 1 */
+#define PMRN_UPMLCA0	0x080	/* User PM Local Control A0 */
+#define PMRN_UPMLCA1	0x081	/* User PM Local Control A1 */
+#define PMRN_UPMLCA2	0x082	/* User PM Local Control A2 */
+#define PMRN_UPMLCA3	0x083	/* User PM Local Control A3 */
+#define PMRN_UPMLCB0	0x100	/* User PM Local Control B0 */
+#define PMRN_UPMLCB1	0x101	/* User PM Local Control B1 */
+#define PMRN_UPMLCB2	0x102	/* User PM Local Control B2 */
+#define PMRN_UPMLCB3	0x103	/* User PM Local Control B3 */
+#define PMRN_UPMGC0	0x180	/* User PM Global Control 0 */
+
+
+/* Machine State Register (MSR) Fields */
+#define MSR_UCLE	(1<<26)	/* User-mode cache lock enable */
+#define MSR_SPE		(1<<25)	/* Enable SPE */
+#define MSR_DWE		(1<<10)	/* Debug Wait Enable */
+#define MSR_UBLE	(1<<10)	/* BTB lock enable (e500) */
+#define MSR_IS		MSR_IR	/* Instruction Space */
+#define MSR_DS		MSR_DR	/* Data Space */
+#define MSR_PMM		(1<<2)	/* Performance monitor mark bit */
+
+/* Default MSR for kernel mode. */
+#if defined (CONFIG_40x)
+#define MSR_KERNEL	(MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE)
+#elif defined(CONFIG_BOOKE)
+#define MSR_KERNEL	(MSR_ME|MSR_RI|MSR_CE)
+#endif
+
+/* Special Purpose Registers (SPRNs)*/
+#define SPRN_DECAR	0x036	/* Decrementer Auto Reload Register */
+#define SPRN_IVPR	0x03F	/* Interrupt Vector Prefix Register */
+#define SPRN_USPRG0	0x100	/* User Special Purpose Register General 0 */
+#define SPRN_SPRG4R	0x104	/* Special Purpose Register General 4 Read */
+#define SPRN_SPRG5R	0x105	/* Special Purpose Register General 5 Read */
+#define SPRN_SPRG6R	0x106	/* Special Purpose Register General 6 Read */
+#define SPRN_SPRG7R	0x107	/* Special Purpose Register General 7 Read */
+#define SPRN_SPRG4W	0x114	/* Special Purpose Register General 4 Write */
+#define SPRN_SPRG5W	0x115	/* Special Purpose Register General 5 Write */
+#define SPRN_SPRG6W	0x116	/* Special Purpose Register General 6 Write */
+#define SPRN_SPRG7W	0x117	/* Special Purpose Register General 7 Write */
+#define SPRN_DBCR2	0x136	/* Debug Control Register 2 */
+#define SPRN_IAC3	0x13A	/* Instruction Address Compare 3 */
+#define SPRN_IAC4	0x13B	/* Instruction Address Compare 4 */
+#define SPRN_DVC1	0x13E	/* Data Value Compare Register 1 */
+#define SPRN_DVC2	0x13F	/* Data Value Compare Register 2 */
+#define SPRN_IVOR0	0x190	/* Interrupt Vector Offset Register 0 */
+#define SPRN_IVOR1	0x191	/* Interrupt Vector Offset Register 1 */
+#define SPRN_IVOR2	0x192	/* Interrupt Vector Offset Register 2 */
+#define SPRN_IVOR3	0x193	/* Interrupt Vector Offset Register 3 */
+#define SPRN_IVOR4	0x194	/* Interrupt Vector Offset Register 4 */
+#define SPRN_IVOR5	0x195	/* Interrupt Vector Offset Register 5 */
+#define SPRN_IVOR6	0x196	/* Interrupt Vector Offset Register 6 */
+#define SPRN_IVOR7	0x197	/* Interrupt Vector Offset Register 7 */
+#define SPRN_IVOR8	0x198	/* Interrupt Vector Offset Register 8 */
+#define SPRN_IVOR9	0x199	/* Interrupt Vector Offset Register 9 */
+#define SPRN_IVOR10	0x19A	/* Interrupt Vector Offset Register 10 */
+#define SPRN_IVOR11	0x19B	/* Interrupt Vector Offset Register 11 */
+#define SPRN_IVOR12	0x19C	/* Interrupt Vector Offset Register 12 */
+#define SPRN_IVOR13	0x19D	/* Interrupt Vector Offset Register 13 */
+#define SPRN_IVOR14	0x19E	/* Interrupt Vector Offset Register 14 */
+#define SPRN_IVOR15	0x19F	/* Interrupt Vector Offset Register 15 */
+#define SPRN_SPEFSCR	0x200	/* SPE & Embedded FP Status & Control */
+#define SPRN_BBEAR	0x201	/* Branch Buffer Entry Address Register */
+#define SPRN_BBTAR	0x202	/* Branch Buffer Target Address Register */
+#define SPRN_IVOR32	0x210	/* Interrupt Vector Offset Register 32 */
+#define SPRN_IVOR33	0x211	/* Interrupt Vector Offset Register 33 */
+#define SPRN_IVOR34	0x212	/* Interrupt Vector Offset Register 34 */
+#define SPRN_IVOR35	0x213	/* Interrupt Vector Offset Register 35 */
+#define SPRN_MCSRR0	0x23A	/* Machine Check Save and Restore Register 0 */
+#define SPRN_MCSRR1	0x23B	/* Machine Check Save and Restore Register 1 */
+#define SPRN_MCSR	0x23C	/* Machine Check Status Register */
+#define SPRN_MCAR	0x23D	/* Machine Check Address Register */
+#define SPRN_DSRR0	0x23E	/* Debug Save and Restore Register 0 */
+#define SPRN_DSRR1	0x23F	/* Debug Save and Restore Register 1 */
+#define SPRN_MAS0	0x270	/* MMU Assist Register 0 */
+#define SPRN_MAS1	0x271	/* MMU Assist Register 1 */
+#define SPRN_MAS2	0x272	/* MMU Assist Register 2 */
+#define SPRN_MAS3	0x273	/* MMU Assist Register 3 */
+#define SPRN_MAS4	0x274	/* MMU Assist Register 4 */
+#define SPRN_MAS5	0x275	/* MMU Assist Register 5 */
+#define SPRN_MAS6	0x276	/* MMU Assist Register 6 */
+#define SPRN_MAS7	0x3b0	/* MMU Assist Register 7 */
+#define SPRN_PID1	0x279	/* Process ID Register 1 */
+#define SPRN_PID2	0x27A	/* Process ID Register 2 */
+#define SPRN_TLB0CFG	0x2B0	/* TLB 0 Config Register */
+#define SPRN_TLB1CFG	0x2B1	/* TLB 1 Config Register */
+#define SPRN_CCR1	0x378	/* Core Configuration Register 1 */
+#define SPRN_ZPR	0x3B0	/* Zone Protection Register (40x) */
+#define SPRN_MMUCR	0x3B2	/* MMU Control Register */
+#define SPRN_CCR0	0x3B3	/* Core Configuration Register 0 */
+#define SPRN_SGR	0x3B9	/* Storage Guarded Register */
+#define SPRN_DCWR	0x3BA	/* Data Cache Write-thru Register */
+#define SPRN_SLER	0x3BB	/* Little-endian real mode */
+#define SPRN_SU0R	0x3BC	/* "User 0" real mode (40x) */
+#define SPRN_DCMP	0x3D1	/* Data TLB Compare Register */
+#define SPRN_ICDBDR	0x3D3	/* Instruction Cache Debug Data Register */
+#define SPRN_EVPR	0x3D6	/* Exception Vector Prefix Register */
+#define SPRN_L1CSR0	0x3F2	/* L1 Cache Control and Status Register 0 */
+#define SPRN_L1CSR1	0x3F3	/* L1 Cache Control and Status Register 1 */
+#define SPRN_PIT	0x3DB	/* Programmable Interval Timer */
+#define SPRN_DCCR	0x3FA	/* Data Cache Cacheability Register */
+#define SPRN_ICCR	0x3FB	/* Instruction Cache Cacheability Register */
+#define SPRN_SVR	0x3FF	/* System Version Register */
+
+/*
+ * SPRs which have conflicting definitions on true Book E versus classic,
+ * or IBM 40x.
+ */
+#ifdef CONFIG_BOOKE
+#define SPRN_PID	0x030	/* Process ID */
+#define SPRN_PID0	SPRN_PID/* Process ID Register 0 */
+#define SPRN_CSRR0	0x03A	/* Critical Save and Restore Register 0 */
+#define SPRN_CSRR1	0x03B	/* Critical Save and Restore Register 1 */
+#define SPRN_DEAR	0x03D	/* Data Error Address Register */
+#define SPRN_ESR	0x03E	/* Exception Syndrome Register */
+#define SPRN_PIR	0x11E	/* Processor Identification Register */
+#define SPRN_DBSR	0x130	/* Debug Status Register */
+#define SPRN_DBCR0	0x134	/* Debug Control Register 0 */
+#define SPRN_DBCR1	0x135	/* Debug Control Register 1 */
+#define SPRN_IAC1	0x138	/* Instruction Address Compare 1 */
+#define SPRN_IAC2	0x139	/* Instruction Address Compare 2 */
+#define SPRN_DAC1	0x13C	/* Data Address Compare 1 */
+#define SPRN_DAC2	0x13D	/* Data Address Compare 2 */
+#define SPRN_TSR	0x150	/* Timer Status Register */
+#define SPRN_TCR	0x154	/* Timer Control Register */
+#endif /* Book E */
+#ifdef CONFIG_40x
+#define SPRN_PID	0x3B1	/* Process ID */
+#define SPRN_DBCR1	0x3BD	/* Debug Control Register 1 */		
+#define SPRN_ESR	0x3D4	/* Exception Syndrome Register */
+#define SPRN_DEAR	0x3D5	/* Data Error Address Register */
+#define SPRN_TSR	0x3D8	/* Timer Status Register */
+#define SPRN_TCR	0x3DA	/* Timer Control Register */
+#define SPRN_SRR2	0x3DE	/* Save/Restore Register 2 */
+#define SPRN_SRR3	0x3DF	/* Save/Restore Register 3 */
+#define SPRN_DBSR	0x3F0	/* Debug Status Register */		
+#define SPRN_DBCR0	0x3F2	/* Debug Control Register 0 */
+#define SPRN_DAC1	0x3F6	/* Data Address Compare 1 */
+#define SPRN_DAC2	0x3F7	/* Data Address Compare 2 */
+#define SPRN_CSRR0	SPRN_SRR2 /* Critical Save and Restore Register 0 */
+#define SPRN_CSRR1	SPRN_SRR3 /* Critical Save and Restore Register 1 */
+#endif
+
+/* Bit definitions for CCR1. */
+#define	CCR1_DPC	0x00000100 /* Disable L1 I-Cache/D-Cache parity checking */
+#define	CCR1_TCS	0x00000080 /* Timer Clock Select */
+
+/* Bit definitions for the MCSR. */
+#ifdef CONFIG_440A
+#define MCSR_MCS	0x80000000 /* Machine Check Summary */
+#define MCSR_IB		0x40000000 /* Instruction PLB Error */
+#define MCSR_DRB	0x20000000 /* Data Read PLB Error */
+#define MCSR_DWB	0x10000000 /* Data Write PLB Error */
+#define MCSR_TLBP	0x08000000 /* TLB Parity Error */
+#define MCSR_ICP	0x04000000 /* I-Cache Parity Error */
+#define MCSR_DCSP	0x02000000 /* D-Cache Search Parity Error */
+#define MCSR_DCFP	0x01000000 /* D-Cache Flush Parity Error */
+#define MCSR_IMPE	0x00800000 /* Imprecise Machine Check Exception */
+#endif
+#ifdef CONFIG_E500
+#define MCSR_MCP 	0x80000000UL /* Machine Check Input Pin */
+#define MCSR_ICPERR 	0x40000000UL /* I-Cache Parity Error */
+#define MCSR_DCP_PERR 	0x20000000UL /* D-Cache Push Parity Error */
+#define MCSR_DCPERR 	0x10000000UL /* D-Cache Parity Error */
+#define MCSR_GL_CI 	0x00010000UL /* Guarded Load or Cache-Inhibited stwcx. */
+#define MCSR_BUS_IAERR 	0x00000080UL /* Instruction Address Error */
+#define MCSR_BUS_RAERR 	0x00000040UL /* Read Address Error */
+#define MCSR_BUS_WAERR 	0x00000020UL /* Write Address Error */
+#define MCSR_BUS_IBERR 	0x00000010UL /* Instruction Data Error */
+#define MCSR_BUS_RBERR 	0x00000008UL /* Read Data Bus Error */
+#define MCSR_BUS_WBERR 	0x00000004UL /* Write Data Bus Error */
+#define MCSR_BUS_IPERR 	0x00000002UL /* Instruction parity Error */
+#define MCSR_BUS_RPERR 	0x00000001UL /* Read parity Error */
+#endif
+#ifdef CONFIG_E200
+#define MCSR_MCP 	0x80000000UL /* Machine Check Input Pin */
+#define MCSR_CP_PERR 	0x20000000UL /* Cache Push Parity Error */
+#define MCSR_CPERR 	0x10000000UL /* Cache Parity Error */
+#define MCSR_EXCP_ERR 	0x08000000UL /* ISI, ITLB, or Bus Error on 1st insn
+					fetch for an exception handler */
+#define MCSR_BUS_IRERR 	0x00000010UL /* Read Bus Error on instruction fetch*/
+#define MCSR_BUS_DRERR 	0x00000008UL /* Read Bus Error on data load */
+#define MCSR_BUS_WRERR 	0x00000004UL /* Write Bus Error on buffered
+					store or cache line push */
+#endif
+
+/* Bit definitions for the DBSR. */
+/*
+ * DBSR bits which have conflicting definitions on true Book E versus IBM 40x.
+ */
+#ifdef CONFIG_BOOKE
+#define DBSR_IC		0x08000000	/* Instruction Completion */
+#define DBSR_BT		0x04000000	/* Branch Taken */
+#define DBSR_TIE	0x01000000	/* Trap Instruction Event */
+#define DBSR_IAC1	0x00800000	/* Instr Address Compare 1 Event */
+#define DBSR_IAC2	0x00400000	/* Instr Address Compare 2 Event */
+#define DBSR_IAC3	0x00200000	/* Instr Address Compare 3 Event */
+#define DBSR_IAC4	0x00100000	/* Instr Address Compare 4 Event */
+#define DBSR_DAC1R	0x00080000	/* Data Addr Compare 1 Read Event */
+#define DBSR_DAC1W	0x00040000	/* Data Addr Compare 1 Write Event */
+#define DBSR_DAC2R	0x00020000	/* Data Addr Compare 2 Read Event */
+#define DBSR_DAC2W	0x00010000	/* Data Addr Compare 2 Write Event */
+#endif
+#ifdef CONFIG_40x
+#define DBSR_IC		0x80000000	/* Instruction Completion */
+#define DBSR_BT		0x40000000	/* Branch taken */
+#define DBSR_TIE	0x10000000	/* Trap Instruction debug Event */
+#define DBSR_IAC1	0x04000000	/* Instruction Address Compare 1 Event */
+#define DBSR_IAC2	0x02000000	/* Instruction Address Compare 2 Event */
+#define DBSR_IAC3	0x00080000	/* Instruction Address Compare 3 Event */
+#define DBSR_IAC4	0x00040000	/* Instruction Address Compare 4 Event */
+#define DBSR_DAC1R	0x01000000	/* Data Address Compare 1 Read Event */
+#define DBSR_DAC1W	0x00800000	/* Data Address Compare 1 Write Event */
+#define DBSR_DAC2R	0x00400000	/* Data Address Compare 2 Read Event */
+#define DBSR_DAC2W	0x00200000	/* Data Address Compare 2 Write Event */
+#endif
+
+/* Bit definitions related to the ESR. */
+#define ESR_MCI		0x80000000	/* Machine Check - Instruction */
+#define ESR_IMCP	0x80000000	/* Instr. Machine Check - Protection */
+#define ESR_IMCN	0x40000000	/* Instr. Machine Check - Non-config */
+#define ESR_IMCB	0x20000000	/* Instr. Machine Check - Bus error */
+#define ESR_IMCT	0x10000000	/* Instr. Machine Check - Timeout */
+#define ESR_PIL		0x08000000	/* Program Exception - Illegal */
+#define ESR_PPR		0x04000000	/* Program Exception - Priveleged */
+#define ESR_PTR		0x02000000	/* Program Exception - Trap */
+#define ESR_FP		0x01000000	/* Floating Point Operation */
+#define ESR_DST		0x00800000	/* Storage Exception - Data miss */
+#define ESR_DIZ		0x00400000	/* Storage Exception - Zone fault */
+#define ESR_ST		0x00800000	/* Store Operation */
+#define ESR_DLK		0x00200000	/* Data Cache Locking */
+#define ESR_ILK		0x00100000	/* Instr. Cache Locking */
+#define ESR_PUO		0x00040000	/* Unimplemented Operation exception */
+#define ESR_BO		0x00020000	/* Byte Ordering */
+
+/* Bit definitions related to the DBCR0. */
+#define DBCR0_EDM	0x80000000	/* External Debug Mode */
+#define DBCR0_IDM	0x40000000	/* Internal Debug Mode */
+#define DBCR0_RST	0x30000000	/* all the bits in the RST field */
+#define DBCR0_RST_SYSTEM 0x30000000	/* System Reset */
+#define DBCR0_RST_CHIP	0x20000000	/* Chip Reset */
+#define DBCR0_RST_CORE	0x10000000	/* Core Reset */
+#define DBCR0_RST_NONE	0x00000000	/* No Reset */
+#define DBCR0_IC	0x08000000	/* Instruction Completion */
+#define DBCR0_BT	0x04000000	/* Branch Taken */
+#define DBCR0_EDE	0x02000000	/* Exception Debug Event */
+#define DBCR0_TDE	0x01000000	/* TRAP Debug Event */
+#define DBCR0_IA1	0x00800000	/* Instr Addr compare 1 enable */
+#define DBCR0_IA2	0x00400000	/* Instr Addr compare 2 enable */
+#define DBCR0_IA12	0x00200000	/* Instr Addr 1-2 range enable */
+#define DBCR0_IA12X	0x00100000	/* Instr Addr 1-2 range eXclusive */
+#define DBCR0_IA3	0x00080000	/* Instr Addr compare 3 enable */
+#define DBCR0_IA4	0x00040000	/* Instr Addr compare 4 enable */
+#define DBCR0_IA34	0x00020000	/* Instr Addr 3-4 range Enable */
+#define DBCR0_IA34X	0x00010000	/* Instr Addr 3-4 range eXclusive */
+#define DBCR0_IA12T	0x00008000	/* Instr Addr 1-2 range Toggle */
+#define DBCR0_IA34T	0x00004000	/* Instr Addr 3-4 range Toggle */
+#define DBCR0_FT	0x00000001	/* Freeze Timers on debug event */
+
+/* Bit definitions related to the TCR. */
+#define TCR_WP(x)	(((x)&0x3)<<30)	/* WDT Period */
+#define TCR_WP_MASK	TCR_WP(3)
+#define WP_2_17		0		/* 2^17 clocks */
+#define WP_2_21		1		/* 2^21 clocks */
+#define WP_2_25		2		/* 2^25 clocks */
+#define WP_2_29		3		/* 2^29 clocks */
+#define TCR_WRC(x)	(((x)&0x3)<<28)	/* WDT Reset Control */
+#define TCR_WRC_MASK	TCR_WRC(3)
+#define WRC_NONE	0		/* No reset will occur */
+#define WRC_CORE	1		/* Core reset will occur */
+#define WRC_CHIP	2		/* Chip reset will occur */
+#define WRC_SYSTEM	3		/* System reset will occur */
+#define TCR_WIE		0x08000000	/* WDT Interrupt Enable */
+#define TCR_PIE		0x04000000	/* PIT Interrupt Enable */
+#define TCR_DIE		TCR_PIE		/* DEC Interrupt Enable */
+#define TCR_FP(x)	(((x)&0x3)<<24)	/* FIT Period */
+#define TCR_FP_MASK	TCR_FP(3)
+#define FP_2_9		0		/* 2^9 clocks */
+#define FP_2_13		1		/* 2^13 clocks */
+#define FP_2_17		2		/* 2^17 clocks */
+#define FP_2_21		3		/* 2^21 clocks */
+#define TCR_FIE		0x00800000	/* FIT Interrupt Enable */
+#define TCR_ARE		0x00400000	/* Auto Reload Enable */
+
+/* Bit definitions for the TSR. */
+#define TSR_ENW		0x80000000	/* Enable Next Watchdog */
+#define TSR_WIS		0x40000000	/* WDT Interrupt Status */
+#define TSR_WRS(x)	(((x)&0x3)<<28)	/* WDT Reset Status */
+#define WRS_NONE	0		/* No WDT reset occurred */
+#define WRS_CORE	1		/* WDT forced core reset */
+#define WRS_CHIP	2		/* WDT forced chip reset */
+#define WRS_SYSTEM	3		/* WDT forced system reset */
+#define TSR_PIS		0x08000000	/* PIT Interrupt Status */
+#define TSR_DIS		TSR_PIS		/* DEC Interrupt Status */
+#define TSR_FIS		0x04000000	/* FIT Interrupt Status */
+
+/* Bit definitions for the DCCR. */
+#define DCCR_NOCACHE	0		/* Noncacheable */
+#define DCCR_CACHE	1		/* Cacheable */
+
+/* Bit definitions for DCWR. */
+#define DCWR_COPY	0		/* Copy-back */
+#define DCWR_WRITE	1		/* Write-through */
+
+/* Bit definitions for ICCR. */
+#define ICCR_NOCACHE	0		/* Noncacheable */
+#define ICCR_CACHE	1		/* Cacheable */
+
+/* Bit definitions for L1CSR0. */
+#define L1CSR0_CLFC	0x00000100	/* Cache Lock Bits Flash Clear */
+#define L1CSR0_DCFI	0x00000002	/* Data Cache Flash Invalidate */
+#define L1CSR0_CFI	0x00000002	/* Cache Flash Invalidate */
+#define L1CSR0_DCE	0x00000001	/* Data Cache Enable */
+
+/* Bit definitions for L1CSR1. */
+#define L1CSR1_ICLFR	0x00000100	/* Instr Cache Lock Bits Flash Reset */
+#define L1CSR1_ICFI	0x00000002	/* Instr Cache Flash Invalidate */
+#define L1CSR1_ICE	0x00000001	/* Instr Cache Enable */
+
+/* Bit definitions for SGR. */
+#define SGR_NORMAL	0		/* Speculative fetching allowed. */
+#define SGR_GUARDED	1		/* Speculative fetching disallowed. */
+
+/* Bit definitions for SPEFSCR. */
+#define SPEFSCR_SOVH	0x80000000	/* Summary integer overflow high */
+#define SPEFSCR_OVH	0x40000000	/* Integer overflow high */
+#define SPEFSCR_FGH	0x20000000	/* Embedded FP guard bit high */
+#define SPEFSCR_FXH	0x10000000	/* Embedded FP sticky bit high */
+#define SPEFSCR_FINVH	0x08000000	/* Embedded FP invalid operation high */
+#define SPEFSCR_FDBZH	0x04000000	/* Embedded FP div by zero high */
+#define SPEFSCR_FUNFH	0x02000000	/* Embedded FP underflow high */
+#define SPEFSCR_FOVFH	0x01000000	/* Embedded FP overflow high */
+#define SPEFSCR_FINXS	0x00200000	/* Embedded FP inexact sticky */
+#define SPEFSCR_FINVS	0x00100000	/* Embedded FP invalid op. sticky */
+#define SPEFSCR_FDBZS	0x00080000	/* Embedded FP div by zero sticky */
+#define SPEFSCR_FUNFS	0x00040000	/* Embedded FP underflow sticky */
+#define SPEFSCR_FOVFS	0x00020000	/* Embedded FP overflow sticky */
+#define SPEFSCR_MODE	0x00010000	/* Embedded FP mode */
+#define SPEFSCR_SOV	0x00008000	/* Integer summary overflow */
+#define SPEFSCR_OV	0x00004000	/* Integer overflow */
+#define SPEFSCR_FG	0x00002000	/* Embedded FP guard bit */
+#define SPEFSCR_FX	0x00001000	/* Embedded FP sticky bit */
+#define SPEFSCR_FINV	0x00000800	/* Embedded FP invalid operation */
+#define SPEFSCR_FDBZ	0x00000400	/* Embedded FP div by zero */
+#define SPEFSCR_FUNF	0x00000200	/* Embedded FP underflow */
+#define SPEFSCR_FOVF	0x00000100	/* Embedded FP overflow */
+#define SPEFSCR_FINXE	0x00000040	/* Embedded FP inexact enable */
+#define SPEFSCR_FINVE	0x00000020	/* Embedded FP invalid op. enable */
+#define SPEFSCR_FDBZE	0x00000010	/* Embedded FP div by zero enable */
+#define SPEFSCR_FUNFE	0x00000008	/* Embedded FP underflow enable */
+#define SPEFSCR_FOVFE	0x00000004	/* Embedded FP overflow enable */
+#define SPEFSCR_FRMC 	0x00000003	/* Embedded FP rounding mode control */
+
+/*
+ * The IBM-403 is an even more odd special case, as it is much
+ * older than the IBM-405 series.  We put these down here incase someone
+ * wishes to support these machines again.
+ */
+#ifdef CONFIG_403GCX
+/* Special Purpose Registers (SPRNs)*/
+#define SPRN_TBHU	0x3CC	/* Time Base High User-mode */
+#define SPRN_TBLU	0x3CD	/* Time Base Low User-mode */
+#define SPRN_CDBCR	0x3D7	/* Cache Debug Control Register */
+#define SPRN_TBHI	0x3DC	/* Time Base High */
+#define SPRN_TBLO	0x3DD	/* Time Base Low */
+#define SPRN_DBCR	0x3F2	/* Debug Control Regsiter */
+#define SPRN_PBL1	0x3FC	/* Protection Bound Lower 1 */
+#define SPRN_PBL2	0x3FE	/* Protection Bound Lower 2 */
+#define SPRN_PBU1	0x3FD	/* Protection Bound Upper 1 */
+#define SPRN_PBU2	0x3FF	/* Protection Bound Upper 2 */
+
+
+/* Bit definitions for the DBCR. */
+#define DBCR_EDM	DBCR0_EDM
+#define DBCR_IDM	DBCR0_IDM
+#define DBCR_RST(x)	(((x) & 0x3) << 28)
+#define DBCR_RST_NONE	0
+#define DBCR_RST_CORE	1
+#define DBCR_RST_CHIP	2
+#define DBCR_RST_SYSTEM	3
+#define DBCR_IC		DBCR0_IC	/* Instruction Completion Debug Evnt */
+#define DBCR_BT		DBCR0_BT	/* Branch Taken Debug Event */
+#define DBCR_EDE	DBCR0_EDE	/* Exception Debug Event */
+#define DBCR_TDE	DBCR0_TDE	/* TRAP Debug Event */
+#define DBCR_FER	0x00F80000	/* First Events Remaining Mask */
+#define DBCR_FT		0x00040000	/* Freeze Timers on Debug Event */
+#define DBCR_IA1	0x00020000	/* Instr. Addr. Compare 1 Enable */
+#define DBCR_IA2	0x00010000	/* Instr. Addr. Compare 2 Enable */
+#define DBCR_D1R	0x00008000	/* Data Addr. Compare 1 Read Enable */
+#define DBCR_D1W	0x00004000	/* Data Addr. Compare 1 Write Enable */
+#define DBCR_D1S(x)	(((x) & 0x3) << 12)	/* Data Adrr. Compare 1 Size */
+#define DAC_BYTE	0
+#define DAC_HALF	1
+#define DAC_WORD	2
+#define DAC_QUAD	3
+#define DBCR_D2R	0x00000800	/* Data Addr. Compare 2 Read Enable */
+#define DBCR_D2W	0x00000400	/* Data Addr. Compare 2 Write Enable */
+#define DBCR_D2S(x)	(((x) & 0x3) << 8)	/* Data Addr. Compare 2 Size */
+#define DBCR_SBT	0x00000040	/* Second Branch Taken Debug Event */
+#define DBCR_SED	0x00000020	/* Second Exception Debug Event */
+#define DBCR_STD	0x00000010	/* Second Trap Debug Event */
+#define DBCR_SIA	0x00000008	/* Second IAC Enable */
+#define DBCR_SDA	0x00000004	/* Second DAC Enable */
+#define DBCR_JOI	0x00000002	/* JTAG Serial Outbound Int. Enable */
+#define DBCR_JII	0x00000001	/* JTAG Serial Inbound Int. Enable */
+#endif /* 403GCX */
+#endif /* __ASM_POWERPC_REG_BOOKE_H__ */
+#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/rheap.h b/include/asm-powerpc/rheap.h
similarity index 74%
rename from include/asm-ppc/rheap.h
rename to include/asm-powerpc/rheap.h
index 39a10d8..1723817 100644
--- a/include/asm-ppc/rheap.h
+++ b/include/asm-powerpc/rheap.h
@@ -18,7 +18,7 @@
 
 typedef struct _rh_block {
 	struct list_head list;
-	void *start;
+	unsigned long start;
 	int size;
 	const char *owner;
 } rh_block_t;
@@ -37,8 +37,8 @@
 #define RHIF_STATIC_INFO	0x1
 #define RHIF_STATIC_BLOCK	0x2
 
-typedef struct rh_stats_t {
-	void *start;
+typedef struct _rh_stats {
+	unsigned long start;
 	int size;
 	const char *owner;
 } rh_stats_t;
@@ -57,24 +57,24 @@
 		    rh_block_t * block);
 
 /* Attach a free region to manage */
-extern int rh_attach_region(rh_info_t * info, void *start, int size);
+extern int rh_attach_region(rh_info_t * info, unsigned long start, int size);
 
 /* Detach a free region */
-extern void *rh_detach_region(rh_info_t * info, void *start, int size);
+extern unsigned long rh_detach_region(rh_info_t * info, unsigned long start, int size);
 
 /* Allocate the given size from the remote heap (with alignment) */
-extern void *rh_alloc_align(rh_info_t * info, int size, int alignment,
+extern unsigned long rh_alloc_align(rh_info_t * info, int size, int alignment,
 		const char *owner);
 
 /* Allocate the given size from the remote heap */
-extern void *rh_alloc(rh_info_t * info, int size, const char *owner);
+extern unsigned long rh_alloc(rh_info_t * info, int size, const char *owner);
 
 /* Allocate the given size from the given address */
-extern void *rh_alloc_fixed(rh_info_t * info, void *start, int size,
+extern unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size,
 			    const char *owner);
 
 /* Free the allocated area */
-extern int rh_free(rh_info_t * info, void *start);
+extern int rh_free(rh_info_t * info, unsigned long start);
 
 /* Get stats for debugging purposes */
 extern int rh_get_stats(rh_info_t * info, int what, int max_stats,
@@ -84,6 +84,6 @@
 extern void rh_dump(rh_info_t * info);
 
 /* Set owner of taken block */
-extern int rh_set_owner(rh_info_t * info, void *start, const char *owner);
+extern int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner);
 
 #endif				/* __ASM_PPC_RHEAP_H__ */
diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
index 0b00068..3d44446 100644
--- a/include/asm-powerpc/systbl.h
+++ b/include/asm-powerpc/systbl.h
@@ -307,3 +307,4 @@
 COMPAT_SYS_SPU(move_pages)
 SYSCALL_SPU(getcpu)
 COMPAT_SYS(epoll_pwait)
+COMPAT_SYS_SPU(utimensat)
diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h
index 2baedbe..21f004a 100644
--- a/include/asm-powerpc/unistd.h
+++ b/include/asm-powerpc/unistd.h
@@ -326,10 +326,11 @@
 #define __NR_move_pages		301
 #define __NR_getcpu		302
 #define __NR_epoll_pwait	303
+#define __NR_utimensat		304
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		304
+#define __NR_syscalls		305
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff --git a/include/asm-ppc/commproc.h b/include/asm-ppc/commproc.h
index 4f99df1..3972487 100644
--- a/include/asm-ppc/commproc.h
+++ b/include/asm-ppc/commproc.h
@@ -63,20 +63,15 @@
 #define CPM_DATAONLY_SIZE	((uint)0x0700)
 #define CPM_DP_NOSPACE		((uint)0x7fffffff)
 
-static inline long IS_DPERR(const uint offset)
-{
-	return (uint)offset > (uint)-1000L;
-}
-
 /* Export the base address of the communication processor registers
  * and dual port ram.
  */
 extern	cpm8xx_t	*cpmp;		/* Pointer to comm processor */
-extern uint cpm_dpalloc(uint size, uint align);
-extern int cpm_dpfree(uint offset);
-extern uint cpm_dpalloc_fixed(uint offset, uint size, uint align);
+extern unsigned long cpm_dpalloc(uint size, uint align);
+extern int cpm_dpfree(unsigned long offset);
+extern unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align);
 extern void cpm_dpdump(void);
-extern void *cpm_dpram_addr(uint offset);
+extern void *cpm_dpram_addr(unsigned long offset);
 extern uint cpm_dpram_phys(u8* addr);
 extern void cpm_setbrg(uint brg, uint rate);
 
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index 220cc2d..12a2860 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -104,21 +104,16 @@
  */
 #define NUM_CPM_HOST_PAGES	2
 
-static inline long IS_DPERR(const uint offset)
-{
-	return (uint)offset > (uint)-1000L;
-}
-
 /* Export the base address of the communication processor registers
  * and dual port ram.
  */
 extern		cpm_cpm2_t	*cpmp;	 /* Pointer to comm processor */
 
-extern uint cpm_dpalloc(uint size, uint align);
-extern int cpm_dpfree(uint offset);
-extern uint cpm_dpalloc_fixed(uint offset, uint size, uint align);
+extern unsigned long cpm_dpalloc(uint size, uint align);
+extern int cpm_dpfree(unsigned long offset);
+extern unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align);
 extern void cpm_dpdump(void);
-extern void *cpm_dpram_addr(uint offset);
+extern void *cpm_dpram_addr(unsigned long offset);
 extern void cpm_setbrg(uint brg, uint rate);
 extern void cpm2_fastbrg(uint brg, uint rate, int div16);
 extern void cpm2_reset(void);
diff --git a/include/asm-s390/ccwdev.h b/include/asm-s390/ccwdev.h
index 6795ece..4c2e171 100644
--- a/include/asm-s390/ccwdev.h
+++ b/include/asm-s390/ccwdev.h
@@ -16,6 +16,7 @@
 /* structs from asm/cio.h */
 struct irb;
 struct ccw1;
+struct ccw_dev_id;
 
 /* simplified initializers for struct ccw_device:
  * CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one
@@ -175,6 +176,7 @@
 
 extern struct ciw *ccw_device_get_ciw(struct ccw_device *, __u32 cmd);
 extern __u8 ccw_device_get_path_mask(struct ccw_device *);
+extern void ccw_device_get_id(struct ccw_device *, struct ccw_dev_id *);
 
 #define get_ccwdev_lock(x) (x)->ccwlock
 
@@ -184,7 +186,6 @@
 extern struct ccw_device *ccw_device_probe_console(void);
 
 // FIXME: these have to go
-extern int _ccw_device_get_device_number(struct ccw_device *);
 extern int _ccw_device_get_subchannel_number(struct ccw_device *);
 
 extern void *ccw_device_get_chp_desc(struct ccw_device *, int);
diff --git a/include/asm-s390/ipl.h b/include/asm-s390/ipl.h
index bdcd448..2c40fd3 100644
--- a/include/asm-s390/ipl.h
+++ b/include/asm-s390/ipl.h
@@ -79,8 +79,8 @@
  * IPL validity flags
  */
 extern u32 ipl_flags;
-
 extern u32 dump_prefix_page;
+extern unsigned int zfcpdump_prefix_array[];
 
 extern void do_reipl(void);
 extern void ipl_save_parameters(void);
diff --git a/include/asm-s390/param.h b/include/asm-s390/param.h
index 085a7e2..34aaa46 100644
--- a/include/asm-s390/param.h
+++ b/include/asm-s390/param.h
@@ -10,7 +10,7 @@
 #define _ASMS390_PARAM_H
 
 #ifdef __KERNEL__
-# define HZ		100		/* Internal kernel timer frequency */
+# define HZ		CONFIG_HZ	/* Internal kernel timer frequency */
 # define USER_HZ	100		/* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC	(USER_HZ)	/* like times() */
 #endif
diff --git a/include/asm-s390/poll.h b/include/asm-s390/poll.h
index 6f7f65a..c98509d 100644
--- a/include/asm-s390/poll.h
+++ b/include/asm-s390/poll.h
@@ -1,35 +1 @@
-/*
- *  include/asm-s390/poll.h
- *
- *  S390 version
- *
- *  Derived from "include/asm-i386/poll.h"
- */
-
-#ifndef __S390_POLL_H
-#define __S390_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN          0x0001
-#define POLLPRI         0x0002
-#define POLLOUT         0x0004
-#define POLLERR         0x0008
-#define POLLHUP         0x0010
-#define POLLNVAL        0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-sh/poll.h b/include/asm-sh/poll.h
index dbca9b3..c98509d 100644
--- a/include/asm-sh/poll.h
+++ b/include/asm-sh/poll.h
@@ -1,27 +1 @@
-#ifndef __ASM_SH_POLL_H
-#define __ASM_SH_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif /* __ASM_SH_POLL_H */
+#include <asm-generic/poll.h>
diff --git a/include/asm-sh64/poll.h b/include/asm-sh64/poll.h
index 3a6cbad..ca29502 100644
--- a/include/asm-sh64/poll.h
+++ b/include/asm-sh64/poll.h
@@ -1,37 +1,8 @@
 #ifndef __ASM_SH64_POLL_H
 #define __ASM_SH64_POLL_H
 
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * include/asm-sh64/poll.h
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- *
- */
+#include <asm-generic/poll.h>
 
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#undef POLLREMOVE
 
 #endif /* __ASM_SH64_POLL_H */
diff --git a/include/asm-sparc/poll.h b/include/asm-sparc/poll.h
index 26f13fb..091d3ad 100644
--- a/include/asm-sparc/poll.h
+++ b/include/asm-sparc/poll.h
@@ -1,24 +1,12 @@
 #ifndef __SPARC_POLL_H
 #define __SPARC_POLL_H
 
-#define POLLIN		  1
-#define POLLPRI		  2
-#define POLLOUT		  4
-#define POLLERR		  8
-#define POLLHUP		 16
-#define POLLNVAL	 32
-#define POLLRDNORM	 64
 #define POLLWRNORM	POLLOUT
-#define POLLRDBAND	128
 #define POLLWRBAND	256
 #define POLLMSG		512
 #define POLLREMOVE	1024
 #define POLLRDHUP       2048
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
 
 #endif
diff --git a/include/asm-sparc64/openprom.h b/include/asm-sparc64/openprom.h
index e01b805..26ec046 100644
--- a/include/asm-sparc64/openprom.h
+++ b/include/asm-sparc64/openprom.h
@@ -177,7 +177,7 @@
 /* More fun PROM structures for device probing. */
 #define PROMREG_MAX     24
 #define PROMVADDR_MAX   16
-#define PROMINTR_MAX    15
+#define PROMINTR_MAX    32
 
 struct linux_prom_registers {
 	unsigned which_io;	/* hi part of physical address			*/
diff --git a/include/asm-sparc64/poll.h b/include/asm-sparc64/poll.h
index ab6b0d1..ebeeb38 100644
--- a/include/asm-sparc64/poll.h
+++ b/include/asm-sparc64/poll.h
@@ -1,24 +1,12 @@
 #ifndef __SPARC64_POLL_H
 #define __SPARC64_POLL_H
 
-#define POLLIN		  1
-#define POLLPRI		  2
-#define POLLOUT		  4
-#define POLLERR		  8
-#define POLLHUP		 16
-#define POLLNVAL	 32
-#define POLLRDNORM	 64
 #define POLLWRNORM	POLLOUT
-#define POLLRDBAND	128
 #define POLLWRBAND	256
 #define POLLMSG		512
 #define POLLREMOVE	1024
 #define POLLRDHUP       2048
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
 
 #endif
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 261e2f4..18a13ba 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -22,6 +22,7 @@
 					 	   0-0xBFFFFFFF for user
 						   0-0xFFFFFFFF for kernel */
 	struct restart_block    restart_block;
+	struct thread_info	*real_thread;    /* Points to non-IRQ stack */
 };
 
 #define INIT_THREAD_INFO(tsk)			\
@@ -35,6 +36,7 @@
 	.restart_block =  {			\
 		.fn =  do_no_restart_syscall,	\
 	},					\
+	.real_thread = NULL,			\
 }
 
 #define init_thread_info	(init_thread_union.thread_info)
diff --git a/include/asm-v850/poll.h b/include/asm-v850/poll.h
index c10176c..803cad0 100644
--- a/include/asm-v850/poll.h
+++ b/include/asm-v850/poll.h
@@ -1,24 +1,9 @@
 #ifndef __V850_POLL_H__
 #define __V850_POLL_H__
 
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-#define POLLRDNORM	0x0040
 #define POLLWRNORM	POLLOUT
-#define POLLRDBAND	0x0080
 #define POLLWRBAND	0x0100
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
 
 #endif /* __V850_POLL_H__ */
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h
index a09fe85..a094276 100644
--- a/include/asm-x86_64/alternative.h
+++ b/include/asm-x86_64/alternative.h
@@ -103,6 +103,12 @@
 		      ".previous" : output : [feat] "i" (feature), ##input)
 
 /*
+ * use this macro(s) if you need more than one output parameter
+ * in alternative_io
+ */
+#define ASM_OUTPUT2(a, b) a, b
+
+/*
  * Alternative inline assembly for SMP.
  *
  * The LOCK_PREFIX macro defined here replaces the LOCK and
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index dee632f..e327c83 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -80,6 +80,15 @@
 #define __PHYSICAL_START	CONFIG_PHYSICAL_START
 #define __KERNEL_ALIGN		0x200000
 
+/*
+ * Make sure kernel is aligned to 2MB address. Catching it at compile
+ * time is better. Change your config file and compile the kernel
+ * for a 2MB aligned address (CONFIG_PHYSICAL_START)
+ */
+#if (CONFIG_PHYSICAL_START % __KERNEL_ALIGN) != 0
+#error "CONFIG_PHYSICAL_START must be a multiple of 2MB"
+#endif
+
 #define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)
 #define __START_KERNEL_map	_AC(0xffffffff80000000, UL)
 #define __PAGE_OFFSET           _AC(0xffff810000000000, UL)
diff --git a/include/asm-x86_64/poll.h b/include/asm-x86_64/poll.h
index c0475a9..c98509d 100644
--- a/include/asm-x86_64/poll.h
+++ b/include/asm-x86_64/poll.h
@@ -1,27 +1 @@
-#ifndef __x86_64_POLL_H
-#define __x86_64_POLL_H
-
-/* These are specified by iBCS2 */
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-/* The rest seem to be more-or-less nonstandard. Check them! */
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
-#define POLLWRNORM	0x0100
-#define POLLWRBAND	0x0200
-#define POLLMSG		0x0400
-#define POLLREMOVE	0x1000
-#define POLLRDHUP       0x2000
-
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
-
-#endif
+#include <asm-generic/poll.h>
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 5957039..ae1ed05 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -621,6 +621,15 @@
 __SYSCALL(__NR_move_pages, sys_move_pages)
 #define __NR_utimensat		280
 __SYSCALL(__NR_utimensat, sys_utimensat)
+#define __IGNORE_getcpu		/* implemented as a vsyscall */
+#define __NR_epoll_pwait	281
+__SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
+#define __NR_signalfd		282
+__SYSCALL(__NR_signalfd, sys_signalfd)
+#define __NR_timerfd		282
+__SYSCALL(__NR_timerfd, sys_timerfd)
+#define __NR_eventfd		283
+__SYSCALL(__NR_eventfd, sys_eventfd)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h
index 6fd9477..9d2d599 100644
--- a/include/asm-xtensa/poll.h
+++ b/include/asm-xtensa/poll.h
@@ -11,28 +11,10 @@
 #ifndef _XTENSA_POLL_H
 #define _XTENSA_POLL_H
 
-
-#define POLLIN		0x0001
-#define POLLPRI		0x0002
-#define POLLOUT		0x0004
-
-#define POLLERR		0x0008
-#define POLLHUP		0x0010
-#define POLLNVAL	0x0020
-
-#define POLLRDNORM	0x0040
-#define POLLRDBAND	0x0080
 #define POLLWRNORM	POLLOUT
 #define POLLWRBAND	0x0100
-
-#define POLLMSG		0x0400
 #define POLLREMOVE	0x0800
-#define POLLRDHUP       0x2000
 
-struct pollfd {
-	int fd;
-	short events;
-	short revents;
-};
+#include <asm-generic/poll.h>
 
 #endif /* _XTENSA_POLL_H */
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 94cc04a..bcd01f2 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -140,7 +140,6 @@
 header-y += sockios.h
 header-y += som.h
 header-y += sound.h
-header-y += synclink.h
 header-y += taskstats.h
 header-y += telephony.h
 header-y += termios.h
@@ -191,6 +190,7 @@
 unifdef-y += errqueue.h
 unifdef-y += ethtool.h
 unifdef-y += eventpoll.h
+unifdef-y += signalfd.h
 unifdef-y += ext2_fs.h
 unifdef-y += ext3_fs.h
 unifdef-y += fb.h
@@ -320,6 +320,7 @@
 unifdef-y += soundcard.h
 unifdef-y += stat.h
 unifdef-y += stddef.h
+unifdef-y += synclink.h
 unifdef-y += sysctl.h
 unifdef-y += tcp.h
 unifdef-y += time.h
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 8bcfaa4..fccd8b5 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -182,7 +182,8 @@
 extern int ec_write(u8 addr, u8 val);
 extern int ec_transaction(u8 command,
                           const u8 *wdata, unsigned wdata_len,
-                          u8 *rdata, unsigned rdata_len);
+                          u8 *rdata, unsigned rdata_len,
+			  int force_poll);
 
 #endif /*CONFIG_ACPI_EC*/
 
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 43dc2eb..b903fc0 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -119,6 +119,12 @@
 
 	struct list_head	ki_list;	/* the aio core uses this
 						 * for cancellation */
+
+	/*
+	 * If the aio_resfd field of the userspace iocb is not zero,
+	 * this is the underlying file* to deliver event to.
+	 */
+	struct file		*ki_eventfd;
 };
 
 #define is_sync_kiocb(iocb)	((iocb)->ki_key == KIOCB_SYNC_KEY)
diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h
index e3ca0a4..9e01729 100644
--- a/include/linux/aio_abi.h
+++ b/include/linux/aio_abi.h
@@ -45,6 +45,14 @@
 	IOCB_CMD_PWRITEV = 8,
 };
 
+/*
+ * Valid flags for the "aio_flags" member of the "struct iocb".
+ *
+ * IOCB_FLAG_RESFD - Set if the "aio_resfd" member of the "struct iocb"
+ *                   is valid.
+ */
+#define IOCB_FLAG_RESFD		(1 << 0)
+
 /* read() from /dev/aio returns these structures. */
 struct io_event {
 	__u64		data;		/* the data field from the iocb */
@@ -84,7 +92,15 @@
 
 	/* extra parameters */
 	__u64	aio_reserved2;	/* TODO: use this for a (struct sigevent *) */
-	__u64	aio_reserved3;
+
+	/* flags for the "struct iocb" */
+	__u32	aio_flags;
+
+	/*
+	 * if the IOCB_FLAG_RESFD flag of "aio_flags" is set, this is an
+	 * eventfd to signal AIO readiness to
+	 */
+	__u32	aio_resfd;
 }; /* 64 bytes */
 
 #undef IFBIG
diff --git a/include/linux/anon_inodes.h b/include/linux/anon_inodes.h
new file mode 100644
index 0000000..b2e1ba3
--- /dev/null
+++ b/include/linux/anon_inodes.h
@@ -0,0 +1,16 @@
+/*
+ *  include/linux/anon_inodes.h
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_ANON_INODES_H
+#define _LINUX_ANON_INODES_H
+
+int anon_inode_getfd(int *pfd, struct inode **pinode, struct file **pfile,
+		     const char *name, const struct file_operations *fops,
+		     void *priv);
+
+#endif /* _LINUX_ANON_INODES_H */
+
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 773e30d..fccc6e5 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -91,6 +91,7 @@
 #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
+#define AUDIT_OBJ_PID		1318	/* ptrace target */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -111,6 +112,7 @@
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG    1799
 #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
+#define AUDIT_ANOM_ABEND            1701 /* Process ended abnormally */
 
 #define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
@@ -148,6 +150,8 @@
 #define AUDIT_CLASS_READ_32 5
 #define AUDIT_CLASS_WRITE 6
 #define AUDIT_CLASS_WRITE_32 7
+#define AUDIT_CLASS_SIGNAL 8
+#define AUDIT_CLASS_SIGNAL_32 9
 
 /* This bitmask is used to validate user input.  It represents all bits that
  * are currently used in an audit field constant understood by the kernel.
@@ -337,6 +341,7 @@
 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
 extern int __init audit_register_class(int class, unsigned *list);
 extern int audit_classify_syscall(int abi, unsigned syscall);
+extern int audit_classify_arch(int arch);
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
 				/* Public API */
@@ -351,7 +356,8 @@
 extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
 				const struct inode *parent);
-extern void __audit_inode_update(const struct inode *inode);
+extern void __audit_ptrace(struct task_struct *t);
+
 static inline int audit_dummy_context(void)
 {
 	void *p = current->audit_context;
@@ -372,9 +378,12 @@
 	if (unlikely(!audit_dummy_context()))
 		__audit_inode_child(dname, inode, parent);
 }
-static inline void audit_inode_update(const struct inode *inode) {
+void audit_core_dumps(long signr);
+
+static inline void audit_ptrace(struct task_struct *t)
+{
 	if (unlikely(!audit_dummy_context()))
-		__audit_inode_update(inode);
+		__audit_ptrace(t);
 }
 
 				/* Private API (for audit.c only) */
@@ -447,6 +456,7 @@
 	return 0;
 }
 extern int audit_n_rules;
+extern int audit_signals;
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -457,10 +467,9 @@
 #define audit_putname(n) do { ; } while (0)
 #define __audit_inode(n,i) do { ; } while (0)
 #define __audit_inode_child(d,i,p) do { ; } while (0)
-#define __audit_inode_update(i) do { ; } while (0)
 #define audit_inode(n,i) do { ; } while (0)
 #define audit_inode_child(d,i,p) do { ; } while (0)
-#define audit_inode_update(i) do { ; } while (0)
+#define audit_core_dumps(i) do { ; } while (0)
 #define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_log_task_context(b) do { ; } while (0)
@@ -477,7 +486,9 @@
 #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
 #define audit_mq_notify(d,n) ({ 0; })
 #define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_ptrace(t) ((void)0)
 #define audit_n_rules 0
+#define audit_signals 0
 #endif
 
 #ifdef CONFIG_AUDIT
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 70a157a..636502c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -225,6 +225,11 @@
 	return lhs->tv_nsec - rhs->tv_nsec;
 }
 
+extern int get_compat_itimerspec(struct itimerspec *dst,
+				 const struct compat_itimerspec __user *src);
+extern int put_compat_itimerspec(struct compat_itimerspec __user *dst,
+				 const struct itimerspec *src);
+
 asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp);
 
 extern int compat_printk(const char *fmt, ...);
diff --git a/include/linux/crc-itu-t.h b/include/linux/crc-itu-t.h
new file mode 100644
index 0000000..84920f3
--- /dev/null
+++ b/include/linux/crc-itu-t.h
@@ -0,0 +1,28 @@
+/*
+ *	crc-itu-t.h - CRC ITU-T V.41 routine
+ *
+ * Implements the standard CRC ITU-T V.41:
+ *   Width 16
+ *   Poly  0x0x1021 (x^16 + x^12 + x^15 + 1)
+ *   Init  0
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#ifndef CRC_ITU_T_H
+#define CRC_ITU_T_H
+
+#include <linux/types.h>
+
+extern u16 const crc_itu_t_table[256];
+
+extern u16 crc_itu_t(u16 crc, const u8 *buffer, size_t len);
+
+static inline u16 crc_itu_t_byte(u16 crc, const u8 data)
+{
+	return (crc << 8) ^ crc_itu_t_table[((crc >> 8) ^ data) & 0xff];
+}
+
+#endif /* CRC_ITU_T_H */
+
diff --git a/include/linux/eventfd.h b/include/linux/eventfd.h
new file mode 100644
index 0000000..0d6ecc6
--- /dev/null
+++ b/include/linux/eventfd.h
@@ -0,0 +1,29 @@
+/*
+ *  include/linux/eventfd.h
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_EVENTFD_H
+#define _LINUX_EVENTFD_H
+
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_EVENTFD
+
+struct file *eventfd_fget(int fd);
+int eventfd_signal(struct file *file, int n);
+
+#else /* CONFIG_EVENTFD */
+
+#define eventfd_fget(fd) ERR_PTR(-ENOSYS)
+#define eventfd_signal(f, n) 0
+
+#endif /* CONFIG_EVENTFD */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_EVENTFD_H */
+
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
new file mode 100644
index 0000000..d4455eb
--- /dev/null
+++ b/include/linux/firewire-cdev.h
@@ -0,0 +1,229 @@
+/*
+ * Char device interface.
+ *
+ * Copyright (C) 2005-2006  Kristian Hoegsberg <krh@bitplanet.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LINUX_FIREWIRE_CDEV_H
+#define _LINUX_FIREWIRE_CDEV_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+#include <linux/firewire-constants.h>
+
+#define FW_CDEV_EVENT_BUS_RESET		0x00
+#define FW_CDEV_EVENT_RESPONSE		0x01
+#define FW_CDEV_EVENT_REQUEST		0x02
+#define FW_CDEV_EVENT_ISO_INTERRUPT	0x03
+
+/* The 'closure' fields are for user space to use.  Data passed in the
+ * 'closure' field for a request will be returned in the corresponding
+ * event.  It's a 64-bit type so that it's a fixed size type big
+ * enough to hold a pointer on all platforms. */
+
+struct fw_cdev_event_common {
+	__u64 closure;
+	__u32 type;
+};
+
+struct fw_cdev_event_bus_reset {
+	__u64 closure;
+	__u32 type;
+	__u32 node_id;
+	__u32 local_node_id;
+	__u32 bm_node_id;
+	__u32 irm_node_id;
+	__u32 root_node_id;
+	__u32 generation;
+};
+
+struct fw_cdev_event_response {
+	__u64 closure;
+	__u32 type;
+	__u32 rcode;
+	__u32 length;
+	__u32 data[0];
+};
+
+struct fw_cdev_event_request {
+	__u64 closure;
+	__u32 type;
+	__u32 tcode;
+	__u64 offset;
+	__u32 handle;
+	__u32 length;
+	__u32 data[0];
+};
+
+struct fw_cdev_event_iso_interrupt {
+	__u64 closure;
+	__u32 type;
+	__u32 cycle;
+	__u32 header_length;	/* Length in bytes of following headers. */
+	__u32 header[0];
+};
+
+union fw_cdev_event {
+	struct fw_cdev_event_common common;
+	struct fw_cdev_event_bus_reset bus_reset;
+	struct fw_cdev_event_response response;
+	struct fw_cdev_event_request request;
+	struct fw_cdev_event_iso_interrupt iso_interrupt;
+};
+
+#define FW_CDEV_IOC_GET_INFO		_IOWR('#', 0x00, struct fw_cdev_get_info)
+#define FW_CDEV_IOC_SEND_REQUEST	_IOW('#', 0x01, struct fw_cdev_send_request)
+#define FW_CDEV_IOC_ALLOCATE		_IOWR('#', 0x02, struct fw_cdev_allocate)
+#define FW_CDEV_IOC_DEALLOCATE		_IOW('#', 0x03, struct fw_cdev_deallocate)
+#define FW_CDEV_IOC_SEND_RESPONSE	_IOW('#', 0x04, struct fw_cdev_send_response)
+#define FW_CDEV_IOC_INITIATE_BUS_RESET	_IOW('#', 0x05, struct fw_cdev_initiate_bus_reset)
+#define FW_CDEV_IOC_ADD_DESCRIPTOR	_IOWR('#', 0x06, struct fw_cdev_add_descriptor)
+#define FW_CDEV_IOC_REMOVE_DESCRIPTOR	_IOW('#', 0x07, struct fw_cdev_remove_descriptor)
+
+#define FW_CDEV_IOC_CREATE_ISO_CONTEXT	_IOWR('#', 0x08, struct fw_cdev_create_iso_context)
+#define FW_CDEV_IOC_QUEUE_ISO		_IOWR('#', 0x09, struct fw_cdev_queue_iso)
+#define FW_CDEV_IOC_START_ISO		_IOW('#', 0x0a, struct fw_cdev_start_iso)
+#define FW_CDEV_IOC_STOP_ISO		_IOW('#', 0x0b, struct fw_cdev_stop_iso)
+
+/* FW_CDEV_VERSION History
+ *
+ * 1	Feb 18, 2007:  Initial version.
+ */
+#define FW_CDEV_VERSION		1
+
+struct fw_cdev_get_info {
+	/* The version field is just a running serial number.  We
+	 * never break backwards compatibility.  Userspace passes in
+	 * the version it expects and the kernel passes back the
+	 * highest version it can provide.  Even if the structs in
+	 * this interface are extended in a later version, the kernel
+	 * will not copy back more data than what was present in the
+	 * interface version userspace expects. */
+	__u32 version;
+
+	/* If non-zero, at most rom_length bytes of config rom will be
+	 * copied into that user space address.  In either case,
+	 * rom_length is updated with the actual length of the config
+	 * rom. */
+	__u32 rom_length;
+	__u64 rom;
+
+	/* If non-zero, a fw_cdev_event_bus_reset struct will be
+	 * copied here with the current state of the bus.  This does
+	 * not cause a bus reset to happen.  The value of closure in
+	 * this and sub-sequent bus reset events is set to
+	 * bus_reset_closure. */
+	__u64 bus_reset;
+	__u64 bus_reset_closure;
+
+	/* The index of the card this devices belongs to. */
+	__u32 card;
+};
+
+struct fw_cdev_send_request {
+	__u32 tcode;
+	__u32 length;
+	__u64 offset;
+	__u64 closure;
+	__u64 data;
+	__u32 generation;
+};
+
+struct fw_cdev_send_response {
+	__u32 rcode;
+	__u32 length;
+	__u64 data;
+	__u32 handle;
+};
+
+struct fw_cdev_allocate {
+	__u64 offset;
+	__u64 closure;
+	__u32 length;
+	__u32 handle;
+};
+
+struct fw_cdev_deallocate {
+	__u32 handle;
+};
+
+#define FW_CDEV_LONG_RESET	0
+#define FW_CDEV_SHORT_RESET	1
+
+struct fw_cdev_initiate_bus_reset {
+	__u32 type;
+};
+
+struct fw_cdev_add_descriptor {
+	__u32 immediate;
+	__u32 key;
+	__u64 data;
+	__u32 length;
+	__u32 handle;
+};
+
+struct fw_cdev_remove_descriptor {
+	__u32 handle;
+};
+
+#define FW_CDEV_ISO_CONTEXT_TRANSMIT	0
+#define FW_CDEV_ISO_CONTEXT_RECEIVE	1
+
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG0		 1
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG1		 2
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG2		 4
+#define FW_CDEV_ISO_CONTEXT_MATCH_TAG3		 8
+#define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS	15
+
+struct fw_cdev_create_iso_context {
+	__u32 type;
+	__u32 header_size;
+	__u32 channel;
+	__u32 speed;
+	__u64 closure;
+	__u32 handle;
+};
+
+struct fw_cdev_iso_packet {
+	__u16 payload_length;	/* Length of indirect payload. */
+	__u32 interrupt : 1;	/* Generate interrupt on this packet */
+	__u32 skip : 1;		/* Set to not send packet at all. */
+	__u32 tag : 2;
+	__u32 sy : 4;
+	__u32 header_length : 8;	/* Length of immediate header. */
+	__u32 header[0];
+};
+
+struct fw_cdev_queue_iso {
+	__u64 packets;
+	__u64 data;
+	__u32 size;
+	__u32 handle;
+};
+
+struct fw_cdev_start_iso {
+	__s32 cycle;
+	__u32 sync;
+	__u32 tags;
+	__u32 handle;
+};
+
+struct fw_cdev_stop_iso {
+	__u32 handle;
+};
+
+#endif /* _LINUX_FIREWIRE_CDEV_H */
diff --git a/include/linux/firewire-constants.h b/include/linux/firewire-constants.h
new file mode 100644
index 0000000..b316770
--- /dev/null
+++ b/include/linux/firewire-constants.h
@@ -0,0 +1,67 @@
+#ifndef _LINUX_FIREWIRE_CONSTANTS_H
+#define _LINUX_FIREWIRE_CONSTANTS_H
+
+#define TCODE_WRITE_QUADLET_REQUEST	0x0
+#define TCODE_WRITE_BLOCK_REQUEST	0x1
+#define TCODE_WRITE_RESPONSE		0x2
+#define TCODE_READ_QUADLET_REQUEST	0x4
+#define TCODE_READ_BLOCK_REQUEST	0x5
+#define TCODE_READ_QUADLET_RESPONSE	0x6
+#define TCODE_READ_BLOCK_RESPONSE	0x7
+#define TCODE_CYCLE_START		0x8
+#define TCODE_LOCK_REQUEST		0x9
+#define TCODE_STREAM_DATA		0xa
+#define TCODE_LOCK_RESPONSE		0xb
+
+#define EXTCODE_MASK_SWAP		0x1
+#define EXTCODE_COMPARE_SWAP		0x2
+#define EXTCODE_FETCH_ADD		0x3
+#define EXTCODE_LITTLE_ADD		0x4
+#define EXTCODE_BOUNDED_ADD		0x5
+#define EXTCODE_WRAP_ADD		0x6
+#define EXTCODE_VENDOR_DEPENDENT	0x7
+
+/* Juju specific tcodes */
+#define TCODE_LOCK_MASK_SWAP		(0x10 | EXTCODE_MASK_SWAP)
+#define TCODE_LOCK_COMPARE_SWAP		(0x10 | EXTCODE_COMPARE_SWAP)
+#define TCODE_LOCK_FETCH_ADD		(0x10 | EXTCODE_FETCH_ADD)
+#define TCODE_LOCK_LITTLE_ADD		(0x10 | EXTCODE_LITTLE_ADD)
+#define TCODE_LOCK_BOUNDED_ADD		(0x10 | EXTCODE_BOUNDED_ADD)
+#define TCODE_LOCK_WRAP_ADD		(0x10 | EXTCODE_WRAP_ADD)
+#define TCODE_LOCK_VENDOR_DEPENDENT	(0x10 | EXTCODE_VENDOR_DEPENDENT)
+
+#define RCODE_COMPLETE			0x0
+#define RCODE_CONFLICT_ERROR		0x4
+#define RCODE_DATA_ERROR		0x5
+#define RCODE_TYPE_ERROR		0x6
+#define RCODE_ADDRESS_ERROR		0x7
+
+/* Juju specific rcodes */
+#define RCODE_SEND_ERROR		0x10
+#define RCODE_CANCELLED			0x11
+#define RCODE_BUSY			0x12
+#define RCODE_GENERATION		0x13
+#define RCODE_NO_ACK			0x14
+
+#define SCODE_100			0x0
+#define SCODE_200			0x1
+#define SCODE_400			0x2
+#define SCODE_800			0x3
+#define SCODE_1600			0x4
+#define SCODE_3200			0x5
+#define SCODE_BETA			0x3
+
+#define ACK_COMPLETE			0x1
+#define ACK_PENDING			0x2
+#define ACK_BUSY_X			0x4
+#define ACK_BUSY_A			0x5
+#define ACK_BUSY_B			0x6
+#define ACK_DATA_ERROR			0xd
+#define ACK_TYPE_ERROR			0xe
+
+#define RETRY_1				0x00
+#define RETRY_X				0x01
+#define RETRY_A				0x02
+#define RETRY_B				0x03
+
+#endif /* _LINUX_FIREWIRE_CONSTANTS_H */
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index f589559..4c03ee3 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -434,6 +434,10 @@
 
 #endif
 
-#endif
+#else /* CONFIG_BLOCK */
+
+static inline void printk_all_partitions(void) { }
+
+#endif /* CONFIG_BLOCK */
 
 #endif
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 37076b1..827ee74 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -275,6 +275,7 @@
 #define HID_QUIRK_LOGITECH_DESCRIPTOR		0x00100000
 #define HID_QUIRK_DUPLICATE_USAGES		0x00200000
 #define HID_QUIRK_RESET_LEDS			0x00400000
+#define HID_QUIRK_SWAPPED_MIN_MAX		0x00800000
 
 /*
  * This is the global environment of the parser. This information is
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 45170b2..276ccaa 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -65,9 +65,9 @@
 	.posix_timers	 = LIST_HEAD_INIT(sig.posix_timers),		\
 	.cpu_timers	= INIT_CPU_TIMERS(sig.cpu_timers),		\
 	.rlim		= INIT_RLIMITS,					\
-	.pgrp		= 1,						\
+	.pgrp		= 0,						\
 	.tty_old_pgrp   = NULL,						\
-	{ .__session      = 1},						\
+	{ .__session      = 0},						\
 }
 
 extern struct nsproxy init_nsproxy;
@@ -84,10 +84,33 @@
 	.count		= ATOMIC_INIT(1), 				\
 	.action		= { { { .sa_handler = NULL, } }, },		\
 	.siglock	= __SPIN_LOCK_UNLOCKED(sighand.siglock),	\
+	.signalfd_list	= LIST_HEAD_INIT(sighand.signalfd_list),	\
 }
 
 extern struct group_info init_groups;
 
+#define INIT_STRUCT_PID {						\
+	.count 		= ATOMIC_INIT(1),				\
+	.nr		= 0, 						\
+	/* Don't put this struct pid in pid_hash */			\
+	.pid_chain	= { .next = NULL, .pprev = NULL },		\
+	.tasks		= {						\
+		{ .first = &init_task.pids[PIDTYPE_PID].node },		\
+		{ .first = &init_task.pids[PIDTYPE_PGID].node },	\
+		{ .first = &init_task.pids[PIDTYPE_SID].node },		\
+	},								\
+	.rcu		= RCU_HEAD_INIT,				\
+}
+
+#define INIT_PID_LINK(type) 					\
+{								\
+	.node = {						\
+		.next = NULL,					\
+		.pprev = &init_struct_pid.tasks[type].first,	\
+	},							\
+	.pid = &init_struct_pid,				\
+}
+
 /*
  *  INIT_TASK is used to set up the first task table, touch at
  * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -139,6 +162,11 @@
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
 	.fs_excl	= ATOMIC_INIT(0),				\
 	.pi_lock	= __SPIN_LOCK_UNLOCKED(tsk.pi_lock),		\
+	.pids = {							\
+		[PIDTYPE_PID]  = INIT_PID_LINK(PIDTYPE_PID),		\
+		[PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),		\
+		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\
+	},								\
 	INIT_TRACE_IRQFLAGS						\
 	INIT_LOCKDEP							\
 }
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index f7b01b9..5323f62 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -241,6 +241,16 @@
 #define save_and_cli(x)	save_and_cli(&x)
 #endif /* CONFIG_SMP */
 
+/* Some architectures might implement lazy enabling/disabling of
+ * interrupts. In some cases, such as stop_machine, we might want
+ * to ensure that after a local_irq_disable(), interrupts have
+ * really been disabled in hardware. Such architectures need to
+ * implement the following hook.
+ */
+#ifndef hard_irq_disable
+#define hard_irq_disable()	do { } while(0)
+#endif
+
 /* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
    frequency threaded job scheduling. For almost all the purposes
    tasklets are more than enough. F.e. all serial device BHs et
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 144b615..eec0d13 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -41,6 +41,16 @@
 #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
 #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
 
+/**
+ * upper_32_bits - return bits 32-63 of a number
+ * @n: the number we're accessing
+ *
+ * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
+ * the "right shift count >= width of type" warning when that quantity is
+ * 32-bits.
+ */
+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
+
 #define	KERN_EMERG	"<0>"	/* system is unusable			*/
 #define	KERN_ALERT	"<1>"	/* action must be taken immediately	*/
 #define	KERN_CRIT	"<2>"	/* critical conditions			*/
@@ -203,6 +213,17 @@
 
 extern void dump_stack(void);
 
+enum {
+	DUMP_PREFIX_NONE,
+	DUMP_PREFIX_ADDRESS,
+	DUMP_PREFIX_OFFSET
+};
+extern void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
+				size_t linebuflen);
+extern void print_hex_dump(const char *level, int prefix_type,
+				void *buf, size_t len);
+#define hex_asc(x)	"0123456789abcdef"[x]
+
 #ifdef DEBUG
 /* If you are writing a driver, please use dev_dbg instead */
 #define pr_debug(fmt,arg...) \
diff --git a/include/linux/magic.h b/include/linux/magic.h
index a9c6567..9d713c0 100644
--- a/include/linux/magic.h
+++ b/include/linux/magic.h
@@ -14,6 +14,7 @@
 #define ISOFS_SUPER_MAGIC	0x9660
 #define JFFS2_SUPER_MAGIC	0x72b6
 #define KVMFS_SUPER_MAGIC	0x19700426
+#define ANON_INODE_FS_MAGIC	0x09041934
 
 #define MINIX_SUPER_MAGIC	0x137F		/* original minix fs */
 #define MINIX_SUPER_MAGIC2	0x138F		/* minix fs, 30 char names */
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index e30687b..d5bb179 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -50,13 +50,16 @@
 	    spinlock_t ptl;
 #endif
 	    struct {			/* SLUB uses */
-		struct page *first_page;	/* Compound pages */
+	    	void **lockless_freelist;
 		struct kmem_cache *slab;	/* Pointer to slab */
 	    };
+	    struct {
+		struct page *first_page;	/* Compound pages */
+	    };
 	};
 	union {
 		pgoff_t index;		/* Our offset within mapping. */
-		void *freelist;		/* SLUB: pointer to free object */
+		void *freelist;		/* SLUB: freelist req. slab lock */
 	};
 	struct list_head lru;		/* Pageout list, eg. active_list
 					 * protected by zone->lru_lock !
diff --git a/include/linux/module.h b/include/linux/module.h
index 792d483..e6e0f86 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -124,7 +124,7 @@
  */
 #define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
 
-/* Author, ideally of form NAME <EMAIL>[, NAME <EMAIL>]*[ and NAME <EMAIL>] */
+/* Author, ideally of form NAME[, NAME]*[ and NAME] */
 #define MODULE_AUTHOR(_author) MODULE_INFO(author, _author)
   
 /* What your module does. */
diff --git a/include/linux/mpage.h b/include/linux/mpage.h
index cc5fb75..068a0c9 100644
--- a/include/linux/mpage.h
+++ b/include/linux/mpage.h
@@ -12,7 +12,6 @@
 #ifdef CONFIG_BLOCK
 
 struct writeback_control;
-typedef int (writepage_t)(struct page *page, struct writeback_control *wbc);
 
 int mpage_readpages(struct address_space *mapping, struct list_head *pages,
 				unsigned nr_pages, get_block_t get_block);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3044622..f671cd2 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -467,6 +467,8 @@
 	/* device index hash chain */
 	struct hlist_node	index_hlist;
 
+	struct net_device	*link_watch_next;
+
 	/* register/unregister state machine */
 	enum { NETREG_UNINITIALIZED=0,
 	       NETREG_REGISTERED,	/* completed register_netdevice */
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 022edfa..7e733a6 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -54,6 +54,14 @@
 	unsigned char data[0];
 };
 
+#define XT_TARGET_INIT(__name, __size)					       \
+{									       \
+	.target.u.user = {						       \
+		.target_size	= XT_ALIGN(__size),			       \
+		.name		= __name,				       \
+	},								       \
+}
+
 struct xt_standard_target
 {
 	struct xt_entry_target target;
diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h
index 24c8786d..584cd1b 100644
--- a/include/linux/netfilter_arp/arp_tables.h
+++ b/include/linux/netfilter_arp/arp_tables.h
@@ -238,6 +238,47 @@
  */
 #ifdef __KERNEL__
 
+/* Standard entry. */
+struct arpt_standard
+{
+	struct arpt_entry entry;
+	struct arpt_standard_target target;
+};
+
+struct arpt_error_target
+{
+	struct arpt_entry_target target;
+	char errorname[ARPT_FUNCTION_MAXNAMELEN];
+};
+
+struct arpt_error
+{
+	struct arpt_entry entry;
+	struct arpt_error_target target;
+};
+
+#define ARPT_ENTRY_INIT(__size)						       \
+{									       \
+	.target_offset	= sizeof(struct arpt_entry),			       \
+	.next_offset	= (__size),					       \
+}
+
+#define ARPT_STANDARD_INIT(__verdict)					       \
+{									       \
+	.entry		= ARPT_ENTRY_INIT(sizeof(struct arpt_standard)),       \
+	.target		= XT_TARGET_INIT(ARPT_STANDARD_TARGET,		       \
+					 sizeof(struct arpt_standard_target)), \
+	.target.verdict	= -(__verdict) - 1,				       \
+}
+
+#define ARPT_ERROR_INIT							       \
+{									       \
+	.entry		= ARPT_ENTRY_INIT(sizeof(struct arpt_error)),	       \
+	.target		= XT_TARGET_INIT(ARPT_ERROR_TARGET,		       \
+					 sizeof(struct arpt_error_target)),    \
+	.target.errorname = "ERROR",					       \
+}
+
 #define arpt_register_target(tgt) 	\
 ({	(tgt)->family = NF_ARP;		\
  	xt_register_target(tgt); })
diff --git a/include/linux/netfilter_ipv4/ip_tables.h b/include/linux/netfilter_ipv4/ip_tables.h
index 9527296..2f46dd7 100644
--- a/include/linux/netfilter_ipv4/ip_tables.h
+++ b/include/linux/netfilter_ipv4/ip_tables.h
@@ -295,6 +295,28 @@
 	struct ipt_error_target target;
 };
 
+#define IPT_ENTRY_INIT(__size)						       \
+{									       \
+	.target_offset	= sizeof(struct ipt_entry),			       \
+	.next_offset	= (__size),					       \
+}
+
+#define IPT_STANDARD_INIT(__verdict)					       \
+{									       \
+	.entry		= IPT_ENTRY_INIT(sizeof(struct ipt_standard)),	       \
+	.target		= XT_TARGET_INIT(IPT_STANDARD_TARGET,		       \
+					 sizeof(struct xt_standard_target)),   \
+	.target.verdict	= -(__verdict) - 1,				       \
+}
+
+#define IPT_ERROR_INIT							       \
+{									       \
+	.entry		= IPT_ENTRY_INIT(sizeof(struct ipt_error)),	       \
+	.target		= XT_TARGET_INIT(IPT_ERROR_TARGET,		       \
+					 sizeof(struct ipt_error_target)),     \
+	.target.errorname = "ERROR",					       \
+}
+
 extern unsigned int ipt_do_table(struct sk_buff **pskb,
 				 unsigned int hook,
 				 const struct net_device *in,
diff --git a/include/linux/netfilter_ipv6/ip6_tables.h b/include/linux/netfilter_ipv6/ip6_tables.h
index 61aa104..4686f83 100644
--- a/include/linux/netfilter_ipv6/ip6_tables.h
+++ b/include/linux/netfilter_ipv6/ip6_tables.h
@@ -123,6 +123,28 @@
 	struct ip6t_error_target target;
 };
 
+#define IP6T_ENTRY_INIT(__size)						       \
+{									       \
+	.target_offset	= sizeof(struct ip6t_entry),			       \
+	.next_offset	= (__size),					       \
+}
+
+#define IP6T_STANDARD_INIT(__verdict)					       \
+{									       \
+	.entry		= IP6T_ENTRY_INIT(sizeof(struct ip6t_standard)),       \
+	.target		= XT_TARGET_INIT(IP6T_STANDARD_TARGET,		       \
+					 sizeof(struct ip6t_standard_target)), \
+	.target.verdict	= -(__verdict) - 1,				       \
+}
+
+#define IP6T_ERROR_INIT							       \
+{									       \
+	.entry		= IP6T_ENTRY_INIT(sizeof(struct ip6t_error)),	       \
+	.target		= XT_TARGET_INIT(IP6T_ERROR_TARGET,		       \
+					 sizeof(struct ip6t_error_target)),    \
+	.target.errorname = "ERROR",					       \
+}
+
 /*
  * New IP firewall options for [gs]etsockopt at the RAW IP level.
  * Unlike BSD Linux inherits IP options so you don't have to use
diff --git a/include/linux/pid.h b/include/linux/pid.h
index 2ac27f9..1e0e4e3 100644
--- a/include/linux/pid.h
+++ b/include/linux/pid.h
@@ -51,6 +51,8 @@
 	struct rcu_head rcu;
 };
 
+extern struct pid init_struct_pid;
+
 struct pid_link
 {
 	struct hlist_node node;
@@ -76,8 +78,7 @@
  * write-held.
  */
 extern int FASTCALL(attach_pid(struct task_struct *task,
-				enum pid_type type, int nr));
-
+				enum pid_type type, struct pid *pid));
 extern void FASTCALL(detach_pid(struct task_struct *task, enum pid_type));
 extern void FASTCALL(transfer_pid(struct task_struct *old,
 				  struct task_struct *new, enum pid_type));
diff --git a/include/linux/pmu.h b/include/linux/pmu.h
index 37ca573..5ad913f 100644
--- a/include/linux/pmu.h
+++ b/include/linux/pmu.h
@@ -226,7 +226,7 @@
 extern void pmu_backlight_init(void);
 
 /* some code needs to know if the PMU was suspended for hibernation */
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
 extern int pmu_sys_suspended;
 #else
 /* if power management is not configured it can't be suspended */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 17b72d8..a81897e 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -88,6 +88,7 @@
 
 struct exec_domain;
 struct futex_pi_state;
+struct bio;
 
 /*
  * List of flags we want to share for kernel threads,
@@ -391,6 +392,7 @@
 	atomic_t		count;
 	struct k_sigaction	action[_NSIG];
 	spinlock_t		siglock;
+	struct list_head        signalfd_list;
 };
 
 struct pacct_struct {
@@ -469,6 +471,7 @@
 	cputime_t utime, stime, cutime, cstime;
 	unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw;
 	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
+	unsigned long inblock, oublock, cinblock, coublock;
 
 	/*
 	 * Cumulative ns of scheduled CPU time for dead threads in the
@@ -1014,6 +1017,9 @@
 /* journalling filesystem info */
 	void *journal_info;
 
+/* stacked block device info */
+	struct bio *bio_list, **bio_tail;
+
 /* VM state */
 	struct reclaim_state *reclaim_state;
 
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3fa0fab..9a5eac5 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -233,6 +233,7 @@
 	return sig <= _NSIG ? 1 : 0;
 }
 
+extern int next_signal(struct sigpending *pending, sigset_t *mask);
 extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
 extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
 extern long do_sigpending(void __user *, unsigned long);
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
new file mode 100644
index 0000000..5104294
--- /dev/null
+++ b/include/linux/signalfd.h
@@ -0,0 +1,97 @@
+/*
+ *  include/linux/signalfd.h
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_SIGNALFD_H
+#define _LINUX_SIGNALFD_H
+
+
+struct signalfd_siginfo {
+	__u32 signo;
+	__s32 err;
+	__s32 code;
+	__u32 pid;
+	__u32 uid;
+	__s32 fd;
+	__u32 tid;
+	__u32 band;
+	__u32 overrun;
+	__u32 trapno;
+	__s32 status;
+	__s32 svint;
+	__u64 svptr;
+	__u64 utime;
+	__u64 stime;
+	__u64 addr;
+
+	/*
+	 * Pad strcture to 128 bytes. Remember to update the
+	 * pad size when you add new memebers. We use a fixed
+	 * size structure to avoid compatibility problems with
+	 * future versions, and we leave extra space for additional
+	 * members. We use fixed size members because this strcture
+	 * comes out of a read(2) and we really don't want to have
+	 * a compat on read(2).
+	 */
+	__u8 __pad[48];
+};
+
+
+#ifdef __KERNEL__
+
+#ifdef CONFIG_SIGNALFD
+
+/*
+ * Deliver the signal to listening signalfd. This must be called
+ * with the sighand lock held. Same are the following that end up
+ * calling signalfd_deliver().
+ */
+void signalfd_deliver(struct task_struct *tsk, int sig);
+
+/*
+ * No need to fall inside signalfd_deliver() if no signal listeners
+ * are available.
+ */
+static inline void signalfd_notify(struct task_struct *tsk, int sig)
+{
+	if (unlikely(!list_empty(&tsk->sighand->signalfd_list)))
+		signalfd_deliver(tsk, sig);
+}
+
+/*
+ * The signal -1 is used to notify the signalfd that the sighand
+ * is on its way to be detached.
+ */
+static inline void signalfd_detach_locked(struct task_struct *tsk)
+{
+	if (unlikely(!list_empty(&tsk->sighand->signalfd_list)))
+		signalfd_deliver(tsk, -1);
+}
+
+static inline void signalfd_detach(struct task_struct *tsk)
+{
+	struct sighand_struct *sighand = tsk->sighand;
+
+	if (unlikely(!list_empty(&sighand->signalfd_list))) {
+		spin_lock_irq(&sighand->siglock);
+		signalfd_deliver(tsk, -1);
+		spin_unlock_irq(&sighand->siglock);
+	}
+}
+
+#else /* CONFIG_SIGNALFD */
+
+#define signalfd_deliver(t, s) do { } while (0)
+#define signalfd_notify(t, s) do { } while (0)
+#define signalfd_detach_locked(t) do { } while (0)
+#define signalfd_detach(t) do { } while (0)
+
+#endif /* CONFIG_SIGNALFD */
+
+#endif /* __KERNEL__ */
+
+#endif /* _LINUX_SIGNALFD_H */
+
diff --git a/include/linux/synclink.h b/include/linux/synclink.h
index c8b0426..5562fbf 100644
--- a/include/linux/synclink.h
+++ b/include/linux/synclink.h
@@ -291,4 +291,28 @@
 #define MGSL_IOCGGPIO		_IOR(MGSL_MAGIC_IOC,17,struct gpio_desc)
 #define MGSL_IOCWAITGPIO	_IOWR(MGSL_MAGIC_IOC,18,struct gpio_desc)
 
+#ifdef __KERNEL__
+/* provide 32 bit ioctl compatibility on 64 bit systems */
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
+struct MGSL_PARAMS32 {
+	compat_ulong_t	mode;
+	unsigned char	loopback;
+	unsigned short	flags;
+	unsigned char	encoding;
+	compat_ulong_t	clock_speed;
+	unsigned char	addr_filter;
+	unsigned short	crc_type;
+	unsigned char	preamble_length;
+	unsigned char	preamble;
+	compat_ulong_t	data_rate;
+	unsigned char	data_bits;
+	unsigned char	stop_bits;
+	unsigned char	parity;
+};
+#define MGSL_IOCSPARAMS32 _IOW(MGSL_MAGIC_IOC,0,struct MGSL_PARAMS32)
+#define MGSL_IOCGPARAMS32 _IOR(MGSL_MAGIC_IOC,1,struct MGSL_PARAMS32)
+#endif
+#endif
+
 #endif /* _SYNCLINK_H_ */
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 3139f44..b02070e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -604,6 +604,10 @@
 asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
 				    size_t len);
 asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
+asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask);
+asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+			    const struct itimerspec __user *utmr);
+asmlinkage long sys_eventfd(unsigned int count);
 
 int kernel_execve(const char *filename, char *const argv[], char *const envp[]);
 
diff --git a/include/linux/task_io_accounting_ops.h b/include/linux/task_io_accounting_ops.h
index df2a319..1218733 100644
--- a/include/linux/task_io_accounting_ops.h
+++ b/include/linux/task_io_accounting_ops.h
@@ -10,11 +10,29 @@
 	current->ioac.read_bytes += bytes;
 }
 
+/*
+ * We approximate number of blocks, because we account bytes only.
+ * A 'block' is 512 bytes
+ */
+static inline unsigned long task_io_get_inblock(const struct task_struct *p)
+{
+	return p->ioac.read_bytes >> 9;
+}
+
 static inline void task_io_account_write(size_t bytes)
 {
 	current->ioac.write_bytes += bytes;
 }
 
+/*
+ * We approximate number of blocks, because we account bytes only.
+ * A 'block' is 512 bytes
+ */
+static inline unsigned long task_io_get_oublock(const struct task_struct *p)
+{
+	return p->ioac.write_bytes >> 9;
+}
+
 static inline void task_io_account_cancelled_write(size_t bytes)
 {
 	current->ioac.cancelled_write_bytes += bytes;
@@ -31,10 +49,20 @@
 {
 }
 
+static inline unsigned long task_io_get_inblock(const struct task_struct *p)
+{
+	return 0;
+}
+
 static inline void task_io_account_write(size_t bytes)
 {
 }
 
+static inline unsigned long task_io_get_oublock(const struct task_struct *p)
+{
+	return 0;
+}
+
 static inline void task_io_account_cancelled_write(size_t bytes)
 {
 }
diff --git a/include/linux/timerfd.h b/include/linux/timerfd.h
new file mode 100644
index 0000000..cf2b10d
--- /dev/null
+++ b/include/linux/timerfd.h
@@ -0,0 +1,17 @@
+/*
+ *  include/linux/timerfd.h
+ *
+ *  Copyright (C) 2007  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+
+#ifndef _LINUX_TIMERFD_H
+#define _LINUX_TIMERFD_H
+
+
+#define TFD_TIMER_ABSTIME (1 << 0)
+
+
+
+#endif /* _LINUX_TIMERFD_H */
+
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 659487e..85c95cd 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -52,6 +52,11 @@
  * 	This routine allows the tty driver to implement
  *	device-specific ioctl's.  If the ioctl number passed in cmd
  * 	is not recognized by the driver, it should return ENOIOCTLCMD.
+ *
+ * long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+ * 	                unsigned int cmd, unsigned long arg);
+ *
+ * 	implement ioctl processing for 32 bit process on 64 bit system
  * 
  * void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
@@ -132,6 +137,8 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	int  (*ioctl)(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+	long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+			     unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
@@ -193,6 +200,8 @@
 	int  (*chars_in_buffer)(struct tty_struct *tty);
 	int  (*ioctl)(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg);
+	long (*compat_ioctl)(struct tty_struct *tty, struct file * file,
+			     unsigned int cmd, unsigned long arg);
 	void (*set_termios)(struct tty_struct *tty, struct ktermios * old);
 	void (*throttle)(struct tty_struct * tty);
 	void (*unthrottle)(struct tty_struct * tty);
diff --git a/include/linux/tty_ldisc.h b/include/linux/tty_ldisc.h
index d75932e..6226504 100644
--- a/include/linux/tty_ldisc.h
+++ b/include/linux/tty_ldisc.h
@@ -59,6 +59,11 @@
  * 	low-level driver can "grab" an ioctl request before the line
  * 	discpline has a chance to see it.
  * 
+ * long	(*compat_ioctl)(struct tty_struct * tty, struct file * file,
+ * 		        unsigned int cmd, unsigned long arg);
+ *
+ *      Process ioctl calls from 32-bit process on 64-bit system
+ *
  * void	(*set_termios)(struct tty_struct *tty, struct ktermios * old);
  *
  * 	This function notifies the line discpline that a change has
@@ -118,6 +123,8 @@
 			 const unsigned char * buf, size_t nr);	
 	int	(*ioctl)(struct tty_struct * tty, struct file * file,
 			 unsigned int cmd, unsigned long arg);
+	long	(*compat_ioctl)(struct tty_struct * tty, struct file * file,
+				unsigned int cmd, unsigned long arg);
 	void	(*set_termios)(struct tty_struct *tty, struct ktermios * old);
 	unsigned int (*poll)(struct tty_struct *, struct file *,
 			     struct poll_table_struct *);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index daa6c12..050915b 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -111,9 +111,15 @@
 	balance_dirty_pages_ratelimited_nr(mapping, 1);
 }
 
+typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc,
+				void *data);
+
 int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0);
-extern int generic_writepages(struct address_space *mapping,
-			      struct writeback_control *wbc);
+int generic_writepages(struct address_space *mapping,
+		       struct writeback_control *wbc);
+int write_cache_pages(struct address_space *mapping,
+		      struct writeback_control *wbc, writepage_t writepage,
+		      void *data);
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
 int sync_page_range(struct inode *inode, struct address_space *mapping,
 			loff_t pos, loff_t count);
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 1c6b8bd..4732432 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -183,13 +183,6 @@
 
 extern void nf_conntrack_flush(void);
 
-extern struct nf_conntrack_helper *
-nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
-extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
-
-extern struct nf_conntrack_helper *
-__nf_conntrack_helper_find_byname(const char *name);
-
 extern int nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
 				const struct nf_conntrack_tuple *orig);
 
diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h
index f32f714..96a58d8 100644
--- a/include/net/netfilter/nf_conntrack_l3proto.h
+++ b/include/net/netfilter/nf_conntrack_l3proto.h
@@ -56,9 +56,6 @@
 	 */
 	int (*new)(struct nf_conn *conntrack, const struct sk_buff *skb);
 
-	/* Called when a conntrack entry is destroyed */
-	void (*destroy)(struct nf_conn *conntrack);
-
 	/*
 	 * Called before tracking. 
 	 *	*dataoff: offset of protocol header (TCP, UDP,...) in *pskb
diff --git a/include/net/netfilter/nf_nat_rule.h b/include/net/netfilter/nf_nat_rule.h
index e765654..f974318 100644
--- a/include/net/netfilter/nf_nat_rule.h
+++ b/include/net/netfilter/nf_nat_rule.h
@@ -10,16 +10,11 @@
 			    unsigned int hooknum,
 			    const struct net_device *in,
 			    const struct net_device *out,
-			    struct nf_conn *ct,
-			    struct nf_nat_info *info);
+			    struct nf_conn *ct);
 
 extern unsigned int
-alloc_null_binding(struct nf_conn *ct,
-		   struct nf_nat_info *info,
-		   unsigned int hooknum);
+alloc_null_binding(struct nf_conn *ct, unsigned int hooknum);
 
 extern unsigned int
-alloc_null_binding_confirmed(struct nf_conn *ct,
-			     struct nf_nat_info *info,
-			     unsigned int hooknum);
+alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum);
 #endif /* _NF_NAT_RULE_H */
diff --git a/include/net/udp.h b/include/net/udp.h
index 98755eb..496f89d 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -119,9 +119,16 @@
 }
 
 
+struct udp_get_port_ops {
+	int (*saddr_cmp)(const struct sock *sk1, const struct sock *sk2);
+	int (*saddr_any)(const struct sock *sk);
+	unsigned int (*hash_port_and_rcv_saddr)(__u16 port,
+						const struct sock *sk);
+};
+
 /* net/ipv4/udp.c */
 extern int	udp_get_port(struct sock *sk, unsigned short snum,
-			     int (*saddr_cmp)(const struct sock *, const struct sock *));
+			     const struct udp_get_port_ops *ops);
 extern void	udp_err(struct sk_buff *, u32);
 
 extern int	udp_sendmsg(struct kiocb *iocb, struct sock *sk,
diff --git a/include/net/udplite.h b/include/net/udplite.h
index 635b0ea..50b4b42 100644
--- a/include/net/udplite.h
+++ b/include/net/udplite.h
@@ -120,5 +120,5 @@
 
 extern void	udplite4_register(void);
 extern int 	udplite_get_port(struct sock *sk, unsigned short snum,
-			int (*scmp)(const struct sock *, const struct sock *));
+				 const struct udp_get_port_ops *ops);
 #endif	/* _UDPLITE_H */
diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h
new file mode 100644
index 0000000..4eea637
--- /dev/null
+++ b/include/video/atmel_lcdc.h
@@ -0,0 +1,196 @@
+/*
+ *  Header file for AT91/AT32 LCD Controller
+ *
+ *  Data structure and register user interface
+ *
+ *  Copyright (C) 2007 Atmel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ATMEL_LCDC_H__
+#define __ATMEL_LCDC_H__
+
+ /* LCD Controller info data structure */
+struct atmel_lcdfb_info {
+	spinlock_t		lock;
+	struct fb_info		*info;
+	void __iomem		*mmio;
+	unsigned long		irq_base;
+
+	unsigned int		guard_time;
+	struct platform_device	*pdev;
+	struct clk		*bus_clk;
+	struct clk		*lcdc_clk;
+	unsigned int		default_bpp;
+	unsigned int		default_lcdcon2;
+	unsigned int		default_dmacon;
+	void (*atmel_lcdfb_power_control)(int on);
+	struct fb_monspecs	*default_monspecs;
+	u32			pseudo_palette[16];
+};
+
+#define ATMEL_LCDC_DMABADDR1	0x00
+#define ATMEL_LCDC_DMABADDR2	0x04
+#define ATMEL_LCDC_DMAFRMPT1	0x08
+#define ATMEL_LCDC_DMAFRMPT2	0x0c
+#define ATMEL_LCDC_DMAFRMADD1	0x10
+#define ATMEL_LCDC_DMAFRMADD2	0x14
+
+#define ATMEL_LCDC_DMAFRMCFG	0x18
+#define	ATMEL_LCDC_FRSIZE	(0x7fffff <<  0)
+#define	ATMEL_LCDC_BLENGTH_OFFSET	24
+#define	ATMEL_LCDC_BLENGTH	(0x7f     << ATMEL_LCDC_BLENGTH_OFFSET)
+
+#define ATMEL_LCDC_DMACON	0x1c
+#define	ATMEL_LCDC_DMAEN	(0x1 << 0)
+#define	ATMEL_LCDC_DMARST	(0x1 << 1)
+#define	ATMEL_LCDC_DMABUSY	(0x1 << 2)
+#define		ATMEL_LCDC_DMAUPDT	(0x1 << 3)
+#define		ATMEL_LCDC_DMA2DEN	(0x1 << 4)
+
+#define ATMEL_LCDC_DMA2DCFG	0x20
+#define		ATMEL_LCDC_ADDRINC_OFFSET	0
+#define		ATMEL_LCDC_ADDRINC		(0xffff)
+#define		ATMEL_LCDC_PIXELOFF_OFFSET	24
+#define		ATMEL_LCDC_PIXELOFF		(0x1f << 24)
+
+#define ATMEL_LCDC_LCDCON1	0x0800
+#define	ATMEL_LCDC_BYPASS	(1     <<  0)
+#define	ATMEL_LCDC_CLKVAL_OFFSET	12
+#define	ATMEL_LCDC_CLKVAL	(0x1ff << ATMEL_LCDC_CLKVAL_OFFSET)
+#define	ATMEL_LCDC_LINCNT	(0x7ff << 21)
+
+#define ATMEL_LCDC_LCDCON2	0x0804
+#define	ATMEL_LCDC_DISTYPE	(3 << 0)
+#define		ATMEL_LCDC_DISTYPE_STNMONO	(0 << 0)
+#define		ATMEL_LCDC_DISTYPE_STNCOLOR	(1 << 0)
+#define		ATMEL_LCDC_DISTYPE_TFT		(2 << 0)
+#define	ATMEL_LCDC_SCANMOD	(1 << 2)
+#define		ATMEL_LCDC_SCANMOD_SINGLE	(0 << 2)
+#define		ATMEL_LCDC_SCANMOD_DUAL		(1 << 2)
+#define	ATMEL_LCDC_IFWIDTH	(3 << 3)
+#define		ATMEL_LCDC_IFWIDTH_4		(0 << 3)
+#define		ATMEL_LCDC_IFWIDTH_8		(1 << 3)
+#define		ATMEL_LCDC_IFWIDTH_16		(2 << 3)
+#define	ATMEL_LCDC_PIXELSIZE	(7 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_1		(0 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_2		(1 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_4		(2 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_8		(3 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_16		(4 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_24		(5 << 5)
+#define		ATMEL_LCDC_PIXELSIZE_32		(6 << 5)
+#define	ATMEL_LCDC_INVVD	(1 << 8)
+#define		ATMEL_LCDC_INVVD_NORMAL		(0 << 8)
+#define		ATMEL_LCDC_INVVD_INVERTED	(1 << 8)
+#define	ATMEL_LCDC_INVFRAME	(1 << 9 )
+#define		ATMEL_LCDC_INVFRAME_NORMAL	(0 << 9)
+#define		ATMEL_LCDC_INVFRAME_INVERTED	(1 << 9)
+#define	ATMEL_LCDC_INVLINE	(1 << 10)
+#define		ATMEL_LCDC_INVLINE_NORMAL	(0 << 10)
+#define		ATMEL_LCDC_INVLINE_INVERTED	(1 << 10)
+#define	ATMEL_LCDC_INVCLK	(1 << 11)
+#define		ATMEL_LCDC_INVCLK_NORMAL	(0 << 11)
+#define		ATMEL_LCDC_INVCLK_INVERTED	(1 << 11)
+#define	ATMEL_LCDC_INVDVAL	(1 << 12)
+#define		ATMEL_LCDC_INVDVAL_NORMAL	(0 << 12)
+#define		ATMEL_LCDC_INVDVAL_INVERTED	(1 << 12)
+#define	ATMEL_LCDC_CLKMOD	(1 << 15)
+#define		ATMEL_LCDC_CLKMOD_ACTIVEDISPLAY	(0 << 15)
+#define		ATMEL_LCDC_CLKMOD_ALWAYSACTIVE	(1 << 15)
+#define	ATMEL_LCDC_MEMOR	(1 << 31)
+#define		ATMEL_LCDC_MEMOR_BIG		(0 << 31)
+#define		ATMEL_LCDC_MEMOR_LITTLE		(1 << 31)
+
+#define ATMEL_LCDC_TIM1		0x0808
+#define	ATMEL_LCDC_VFP		(0xff <<  0)
+#define	ATMEL_LCDC_VBP_OFFSET		8
+#define	ATMEL_LCDC_VBP		(0xff <<  ATMEL_LCDC_VBP_OFFSET)
+#define	ATMEL_LCDC_VPW_OFFSET		16
+#define	ATMEL_LCDC_VPW		(0x3f << ATMEL_LCDC_VPW_OFFSET)
+#define	ATMEL_LCDC_VHDLY_OFFSET		24
+#define	ATMEL_LCDC_VHDLY	(0xf  << ATMEL_LCDC_VHDLY_OFFSET)
+
+#define ATMEL_LCDC_TIM2		0x080c
+#define	ATMEL_LCDC_HBP		(0xff  <<  0)
+#define	ATMEL_LCDC_HPW_OFFSET		8
+#define	ATMEL_LCDC_HPW		(0x3f  <<  ATMEL_LCDC_HPW_OFFSET)
+#define	ATMEL_LCDC_HFP_OFFSET		21
+#define	ATMEL_LCDC_HFP		(0x7ff << ATMEL_LCDC_HFP_OFFSET)
+
+#define ATMEL_LCDC_LCDFRMCFG	0x0810
+#define	ATMEL_LCDC_LINEVAL	(0x7ff <<  0)
+#define	ATMEL_LCDC_HOZVAL_OFFSET	21
+#define	ATMEL_LCDC_HOZVAL	(0x7ff << ATMEL_LCDC_HOZVAL_OFFSET)
+
+#define ATMEL_LCDC_FIFO		0x0814
+#define	ATMEL_LCDC_FIFOTH	(0xffff)
+
+#define ATMEL_LCDC_MVAL		0x0818
+
+#define ATMEL_LCDC_DP1_2	0x081c
+#define ATMEL_LCDC_DP4_7	0x0820
+#define ATMEL_LCDC_DP3_5	0x0824
+#define ATMEL_LCDC_DP2_3	0x0828
+#define ATMEL_LCDC_DP5_7	0x082c
+#define ATMEL_LCDC_DP3_4	0x0830
+#define ATMEL_LCDC_DP4_5	0x0834
+#define ATMEL_LCDC_DP6_7	0x0838
+#define	ATMEL_LCDC_DP1_2_VAL	(0xff)
+#define	ATMEL_LCDC_DP4_7_VAL	(0xfffffff)
+#define	ATMEL_LCDC_DP3_5_VAL	(0xfffff)
+#define	ATMEL_LCDC_DP2_3_VAL	(0xfff)
+#define	ATMEL_LCDC_DP5_7_VAL	(0xfffffff)
+#define	ATMEL_LCDC_DP3_4_VAL	(0xffff)
+#define	ATMEL_LCDC_DP4_5_VAL	(0xfffff)
+#define	ATMEL_LCDC_DP6_7_VAL	(0xfffffff)
+
+#define ATMEL_LCDC_PWRCON	0x083c
+#define	ATMEL_LCDC_PWR		(1    <<  0)
+#define	ATMEL_LCDC_GUARDT_OFFSET	1
+#define	ATMEL_LCDC_GUARDT	(0x7f <<  ATMEL_LCDC_GUARDT_OFFSET)
+#define	ATMEL_LCDC_BUSY		(1    << 31)
+
+#define ATMEL_LCDC_CONTRAST_CTR	0x0840
+#define	ATMEL_LCDC_PS		(3 << 0)
+#define		ATMEL_LCDC_PS_DIV1		(0 << 0)
+#define		ATMEL_LCDC_PS_DIV2		(1 << 0)
+#define		ATMEL_LCDC_PS_DIV4		(2 << 0)
+#define		ATMEL_LCDC_PS_DIV8		(3 << 0)
+#define	ATMEL_LCDC_POL		(1 << 2)
+#define		ATMEL_LCDC_POL_NEGATIVE		(0 << 2)
+#define		ATMEL_LCDC_POL_POSITIVE		(1 << 2)
+#define	ATMEL_LCDC_ENA		(1 << 3)
+#define		ATMEL_LCDC_ENA_PWMDISABLE	(0 << 3)
+#define		ATMEL_LCDC_ENA_PWMENABLE	(1 << 3)
+
+#define ATMEL_LCDC_CONTRAST_VAL	0x0844
+#define	ATMEL_LCDC_CVAL	(0xff)
+
+#define ATMEL_LCDC_IER		0x0848
+#define ATMEL_LCDC_IDR		0x084c
+#define ATMEL_LCDC_IMR		0x0850
+#define ATMEL_LCDC_ISR		0x0854
+#define ATMEL_LCDC_ICR		0x0858
+#define	ATMEL_LCDC_LNI		(1 << 0)
+#define	ATMEL_LCDC_LSTLNI	(1 << 1)
+#define	ATMEL_LCDC_EOFI		(1 << 2)
+#define	ATMEL_LCDC_UFLWI	(1 << 4)
+#define	ATMEL_LCDC_OWRI		(1 << 5)
+#define	ATMEL_LCDC_MERI		(1 << 6)
+
+#define ATMEL_LCDC_LUT(n)	(0x0c00 + ((n)*4))
+
+#endif /* __ATMEL_LCDC_H__ */
diff --git a/include/video/pm3fb.h b/include/video/pm3fb.h
index 94c7d2d..d52e45a 100644
--- a/include/video/pm3fb.h
+++ b/include/video/pm3fb.h
@@ -7,9 +7,6 @@
  *  This file is subject to the terms and conditions of the GNU General Public
  *  License. See the file COPYING in the main directory of this archive for
  *  more details.
- *
- *  $Header: /cvsroot/linux/drivers/video/pm3fb.h,v 1.1 2002/02/25 19:11:06 marcelo Exp $
- *
  */
 
 #ifndef PM3FB_H
@@ -1119,117 +1116,10 @@
 /* ***** pm3fb useful define and macro ***** */
 /* ***************************************** */
 
-/* permedia3 -specific definitions */
-#define PM3_SCALE_TO_CLOCK(pr, fe, po) ((2 * PM3_REF_CLOCK * fe) / (pr * (1 << (po))))
-
-/* in case it's not in linux/pci.h */
-#ifndef PCI_DEVICE_ID_3DLABS_PERMEDIA3
-#define PCI_DEVICE_ID_3DLABS_PERMEDIA3 0x000a
-#endif
-
-/* max number of simultaneous board */
-#define PM3_MAX_BOARD 4
-
 /* max size of options */
 #define PM3_OPTIONS_SIZE 256
 
 /* max size of font name */
 #define PM3_FONTNAME_SIZE 40
 
-/* do we want accelerated console  */
-#define PM3FB_USE_ACCEL 1
-
-/* for driver debugging ONLY */
-/* 0 = assert only, 1 = error, 2 = info, 3+ = verbose */
-/* define PM3FB_MASTER_DEBUG 1 */
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3)
-#define PM3FB_TRACE
-#endif /* defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 3) */
-
-#ifdef PM3FB_MASTER_DEBUG
-#define DPRINTK(l,a,b...) do { if ((l) <= PM3FB_MASTER_DEBUG) printk("pm3fb: %s: " a, __FUNCTION__ , ## b); } while (0)
-#define DASSERT(t,a,b...) do { if (!(t)) printk("pm3fb: _assert failed: %s: " a, __FUNCTION__ , ## b); } while (0)
-#ifdef PM3FB_TRACE
-#define DTRACE printk("pm3fb: _enter %s\n", __FUNCTION__)
-#else /* PM3FB_TRACE */
-#define DTRACE
-#endif /* PM3FB_TRACE */
-#else /* PM3FB_MASTER_DEBUG */
-#define DPRINTK(l,a,b...)
-#define DASSERT(t,a,b...)
-#define DTRACE
-#endif /* PM3FB_MASTER_DEBUG */
-
-#if defined(PM3FB_MASTER_DEBUG) && (PM3FB_MASTER_DEBUG >= 2)
-#define PM3_SHOW_CUR_MODE pm3fb_show_cur_mode(l_fb_info)
-#else
-#define PM3_SHOW_CUR_MODE /* pm3fb_show_cur_mode() */
-#endif
-
-/* ******************************************** */
-/* ***** A bunch of register-access macro ***** */
-/* ******************************************** */
-
-#define PM3_WRITE_REG(r, v) fb_writel(v, (l_fb_info->vIOBase + r))
-#define PM3_READ_REG(r) fb_readl((l_fb_info->vIOBase + r))
-
-
-#define depth2bpp(d) ((d + 7L) & ~7L)
-#define depth2ByPP(d) (depth2bpp(d) / 8)
-
-#define depth_supported(d) ((d == 8) || (d == 12) || (d == 15) || (d == 16) || (d==32))
-
-
-#define PM3_WAIT(n) \
-do{ \
-	while(PM3_READ_REG(PM3InFIFOSpace)<(n)); \
-} while(0)
-
-#define PM3_DELAY(x) do { \
-        int delay = x; \
-        unsigned char tmp; \
-        while(delay--){tmp = PM3_READ_REG(PM3InFIFOSpace);}; \
-} while(0)
-
-#define PM3_SLOW_WRITE_REG(r,v)	\
-do{                             \
-    DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in slow write\n"); \
-	mb();                   \
-	PM3_WAIT(1);            \
-	mb();                   \
-    PM3_WRITE_REG(r,v);     \
-} while(0)
-
-#define PM3_SET_INDEX(index) \
-do{ \
-	PM3_SLOW_WRITE_REG(PM3RD_IndexHigh,(((index)>>8)&0xff)); \
-	PM3_SLOW_WRITE_REG(PM3RD_IndexLow,((index)&0xff)); \
-} while(0)
-
-#define PM3_WRITE_DAC_REG(r, v) \
-do { \
-     DASSERT((l_fb_info->vIOBase != (unsigned char*)(-1)), "l_fb_info->vIOBase mapped in write dac reg\n"); \
-     PM3_SET_INDEX(r); \
-     mb(); \
-     PM3_WRITE_REG(PM3RD_IndexedData, v); \
-} while (0)
-
-/* next one is really a function, added as a macro to be consistent */
-#define PM3_READ_DAC_REG(r) pm3fb_read_dac_reg(l_fb_info, r)
-
-
-#define PM3_COLOR(c) \
-do { \
-  if (l_fb_info->current_par->depth == 8) \
-    { \
-      c = (c & 0xFF); \
-      c = c | (c << 8); \
-    } \
-  if ((l_fb_info->current_par->depth == 8) || (depth2bpp(l_fb_info->current_par->depth) == 16)) \
-    { \
-      c = (c & 0xFFFF); \
-      c = c | (c << 16); \
-    } \
-} while (0)
-
 #endif /* PM3FB_H */
diff --git a/init/Kconfig b/init/Kconfig
index e63a017..4e009fd 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -475,13 +475,53 @@
 	  support for "fast userspace mutexes".  The resulting kernel may not
 	  run glibc-based applications correctly.
 
+config ANON_INODES
+	bool "Enable anonymous inode source" if EMBEDDED
+	default y
+	help
+	  Anonymous inode source for pseudo-files like epoll, signalfd,
+	  timerfd and eventfd.
+
+	  If unsure, say Y.
+
 config EPOLL
 	bool "Enable eventpoll support" if EMBEDDED
 	default y
+	depends on ANON_INODES
 	help
 	  Disabling this option will cause the kernel to be built without
 	  support for epoll family of system calls.
 
+config SIGNALFD
+	bool "Enable signalfd() system call" if EMBEDDED
+	depends on ANON_INODES
+	default y
+	help
+	  Enable the signalfd() system call that allows to receive signals
+	  on a file descriptor.
+
+	  If unsure, say Y.
+
+config TIMERFD
+	bool "Enable timerfd() system call" if EMBEDDED
+	depends on ANON_INODES
+	default y
+	help
+	  Enable the timerfd() system call that allows to receive timer
+	  events on a file descriptor.
+
+	  If unsure, say Y.
+
+config EVENTFD
+	bool "Enable eventfd() system call" if EMBEDDED
+	depends on ANON_INODES
+	default y
+	help
+	  Enable the eventfd() system call that allows to receive both
+	  kernel notification (ie. KAIO) or userspace notifications.
+
+	  If unsure, say Y.
+
 config SHMEM
 	bool "Use full shmem filesystem" if EMBEDDED
 	default y
@@ -505,6 +545,7 @@
 config SLUB_DEBUG
 	default y
 	bool "Enable SLUB debugging support" if EMBEDDED
+	depends on SLUB
 	help
 	  SLUB has extensive debug support features. Disabling these can
 	  result in significant savings in code size. This also disables
diff --git a/init/main.c b/init/main.c
index e8d080c..1940fa7 100644
--- a/init/main.c
+++ b/init/main.c
@@ -801,6 +801,7 @@
 	 */
 	init_pid_ns.child_reaper = current;
 
+	__set_special_pids(1, 1);
 	cad_pid = task_pid(current);
 
 	smp_prepare_cpus(max_cpus);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d17821d..fab5707 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -681,6 +681,7 @@
 
 	if (oflag & O_CREAT) {
 		if (dentry->d_inode) {	/* entry already exists */
+			audit_inode(name, dentry->d_inode);
 			error = -EEXIST;
 			if (oflag & O_EXCL)
 				goto out;
@@ -693,6 +694,7 @@
 		error = -ENOENT;
 		if (!dentry->d_inode)
 			goto out;
+		audit_inode(name, dentry->d_inode);
 		filp = do_open(dentry, oflag);
 	}
 
@@ -840,6 +842,7 @@
 	if (unlikely(filp->f_op != &mqueue_file_operations))
 		goto out_fput;
 	info = MQUEUE_I(inode);
+	audit_inode(NULL, inode);
 
 	if (unlikely(!(filp->f_mode & FMODE_WRITE)))
 		goto out_fput;
@@ -923,6 +926,7 @@
 	if (unlikely(filp->f_op != &mqueue_file_operations))
 		goto out_fput;
 	info = MQUEUE_I(inode);
+	audit_inode(NULL, inode);
 
 	if (unlikely(!(filp->f_mode & FMODE_READ)))
 		goto out_fput;
diff --git a/kernel/audit.h b/kernel/audit.h
index a337023..815d6f5 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -83,6 +83,7 @@
 	u32			field_count;
 	char			*filterkey; /* ties events to rules */
 	struct audit_field	*fields;
+	struct audit_field	*arch_f; /* quick access to arch field */
 	struct audit_field	*inode_f; /* quick access to an inode field */
 	struct audit_watch	*watch;	/* associated watch */
 	struct list_head	rlist;	/* entry in audit_watch.rules list */
@@ -131,17 +132,19 @@
 extern int selinux_audit_rule_update(void);
 
 #ifdef CONFIG_AUDITSYSCALL
-extern void __audit_signal_info(int sig, struct task_struct *t);
-static inline void audit_signal_info(int sig, struct task_struct *t)
+extern int __audit_signal_info(int sig, struct task_struct *t);
+static inline int audit_signal_info(int sig, struct task_struct *t)
 {
-	if (unlikely(audit_pid && t->tgid == audit_pid))
-		__audit_signal_info(sig, t);
+	if (unlikely((audit_pid && t->tgid == audit_pid) ||
+		     (audit_signals && !audit_dummy_context())))
+		return __audit_signal_info(sig, t);
+	return 0;
 }
 extern enum audit_state audit_filter_inodes(struct task_struct *,
 					    struct audit_context *);
 extern void audit_set_auditable(struct audit_context *);
 #else
-#define audit_signal_info(s,t)
+#define audit_signal_info(s,t) AUDIT_DISABLED
 #define audit_filter_inodes(t,c) AUDIT_DISABLED
 #define audit_set_auditable(c)
 #endif
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 3749193..6c61263 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -311,6 +311,43 @@
 	return classes[class][AUDIT_WORD(syscall)] & AUDIT_BIT(syscall);
 }
 
+static inline int audit_match_class_bits(int class, u32 *mask)
+{
+	int i;
+
+	if (classes[class]) {
+		for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
+			if (mask[i] & classes[class][i])
+				return 0;
+	}
+	return 1;
+}
+
+static int audit_match_signal(struct audit_entry *entry)
+{
+	struct audit_field *arch = entry->rule.arch_f;
+
+	if (!arch) {
+		/* When arch is unspecified, we must check both masks on biarch
+		 * as syscall number alone is ambiguous. */
+		return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
+					       entry->rule.mask) &&
+			audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
+					       entry->rule.mask));
+	}
+
+	switch(audit_classify_arch(arch->val)) {
+	case 0: /* native */
+		return (audit_match_class_bits(AUDIT_CLASS_SIGNAL,
+					       entry->rule.mask));
+	case 1: /* 32bit on biarch */
+		return (audit_match_class_bits(AUDIT_CLASS_SIGNAL_32,
+					       entry->rule.mask));
+	default:
+		return 1;
+	}
+}
+
 /* Common user-space to kernel rule translation. */
 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 {
@@ -429,6 +466,7 @@
 				err = -EINVAL;
 				goto exit_free;
 			}
+			entry->rule.arch_f = f;
 			break;
 		case AUDIT_PERM:
 			if (f->val & ~15)
@@ -519,7 +557,6 @@
 		case AUDIT_FSGID:
 		case AUDIT_LOGINUID:
 		case AUDIT_PERS:
-		case AUDIT_ARCH:
 		case AUDIT_MSGTYPE:
 		case AUDIT_PPID:
 		case AUDIT_DEVMAJOR:
@@ -531,6 +568,9 @@
 		case AUDIT_ARG2:
 		case AUDIT_ARG3:
 			break;
+		case AUDIT_ARCH:
+			entry->rule.arch_f = f;
+			break;
 		case AUDIT_SUBJ_USER:
 		case AUDIT_SUBJ_ROLE:
 		case AUDIT_SUBJ_TYPE:
@@ -1221,6 +1261,9 @@
 #ifdef CONFIG_AUDITSYSCALL
 	if (!dont_count)
 		audit_n_rules++;
+
+	if (!audit_match_signal(entry))
+		audit_signals++;
 #endif
 	mutex_unlock(&audit_filter_mutex);
 
@@ -1294,6 +1337,9 @@
 #ifdef CONFIG_AUDITSYSCALL
 	if (!dont_count)
 		audit_n_rules--;
+
+	if (!audit_match_signal(entry))
+		audit_signals--;
 #endif
 	mutex_unlock(&audit_filter_mutex);
 
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 628c7ac..e36481e 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -78,17 +78,15 @@
  * for saving names from getname(). */
 #define AUDIT_NAMES    20
 
-/* AUDIT_NAMES_RESERVED is the number of slots we reserve in the
- * audit_context from being used for nameless inodes from
- * path_lookup. */
-#define AUDIT_NAMES_RESERVED 7
-
 /* Indicates that audit should log the full pathname. */
 #define AUDIT_NAME_FULL -1
 
 /* number of audit rules */
 int audit_n_rules;
 
+/* determines whether we collect data for signals sent */
+int audit_signals;
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -114,6 +112,9 @@
 
 #define AUDIT_AUX_IPCPERM	0
 
+/* Number of target pids per aux struct. */
+#define AUDIT_AUX_PIDS	16
+
 struct audit_aux_data_mq_open {
 	struct audit_aux_data	d;
 	int			oflag;
@@ -181,6 +182,13 @@
 	struct vfsmount		*mnt;
 };
 
+struct audit_aux_data_pids {
+	struct audit_aux_data	d;
+	pid_t			target_pid[AUDIT_AUX_PIDS];
+	u32			target_sid[AUDIT_AUX_PIDS];
+	int			pid_count;
+};
+
 /* The per-task audit context. */
 struct audit_context {
 	int		    dummy;	/* must be the first element */
@@ -201,6 +209,7 @@
 	struct vfsmount *   pwdmnt;
 	struct audit_context *previous; /* For nested syscalls */
 	struct audit_aux_data *aux;
+	struct audit_aux_data *aux_pids;
 
 				/* Save things to print about task_struct */
 	pid_t		    pid, ppid;
@@ -209,6 +218,9 @@
 	unsigned long	    personality;
 	int		    arch;
 
+	pid_t		    target_pid;
+	u32		    target_sid;
+
 #if AUDIT_DEBUG
 	int		    put_count;
 	int		    ino_count;
@@ -654,6 +666,10 @@
 		context->aux = aux->next;
 		kfree(aux);
 	}
+	while ((aux = context->aux_pids)) {
+		context->aux_pids = aux->next;
+		kfree(aux);
+	}
 }
 
 static inline void audit_zero_context(struct audit_context *context,
@@ -795,6 +811,29 @@
 	audit_log_task_context(ab);
 }
 
+static int audit_log_pid_context(struct audit_context *context, pid_t pid,
+				 u32 sid)
+{
+	struct audit_buffer *ab;
+	char *s = NULL;
+	u32 len;
+	int rc = 0;
+
+	ab = audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
+	if (!ab)
+		return 1;
+
+	if (selinux_sid_to_string(sid, &s, &len)) {
+		audit_log_format(ab, "opid=%d obj=(none)", pid);
+		rc = 1;
+	} else
+		audit_log_format(ab, "opid=%d  obj=%s", pid, s);
+	audit_log_end(ab);
+	kfree(s);
+
+	return rc;
+}
+
 static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
 {
 	int i, call_panic = 0;
@@ -973,6 +1012,21 @@
 		audit_log_end(ab);
 	}
 
+	for (aux = context->aux_pids; aux; aux = aux->next) {
+		struct audit_aux_data_pids *axs = (void *)aux;
+		int i;
+
+		for (i = 0; i < axs->pid_count; i++)
+			if (audit_log_pid_context(context, axs->target_pid[i],
+						  axs->target_sid[i]))
+				call_panic = 1;
+	}
+
+	if (context->target_pid &&
+	    audit_log_pid_context(context, context->target_pid,
+				  context->target_sid))
+			call_panic = 1;
+
 	if (context->pwd && context->pwdmnt) {
 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
 		if (ab) {
@@ -1193,6 +1247,10 @@
 	} else {
 		audit_free_names(context);
 		audit_free_aux(context);
+		context->aux = NULL;
+		context->aux_pids = NULL;
+		context->target_pid = 0;
+		context->target_sid = 0;
 		kfree(context->filterkey);
 		context->filterkey = NULL;
 		tsk->audit_context = context;
@@ -1226,6 +1284,7 @@
 	context->names[context->name_count].name_len = AUDIT_NAME_FULL;
 	context->names[context->name_count].name_put = 1;
 	context->names[context->name_count].ino  = (unsigned long)-1;
+	context->names[context->name_count].osid = 0;
 	++context->name_count;
 	if (!context->pwd) {
 		read_lock(&current->fs->lock);
@@ -1279,6 +1338,28 @@
 #endif
 }
 
+static int audit_inc_name_count(struct audit_context *context,
+				const struct inode *inode)
+{
+	if (context->name_count >= AUDIT_NAMES) {
+		if (inode)
+			printk(KERN_DEBUG "name_count maxed, losing inode data: "
+			       "dev=%02x:%02x, inode=%lu",
+			       MAJOR(inode->i_sb->s_dev),
+			       MINOR(inode->i_sb->s_dev),
+			       inode->i_ino);
+
+		else
+			printk(KERN_DEBUG "name_count maxed, losing inode data");
+		return 1;
+	}
+	context->name_count++;
+#if AUDIT_DEBUG
+	context->ino_count++;
+#endif
+	return 0;
+}
+
 /* Copy inode data into an audit_names. */
 static void audit_copy_inode(struct audit_names *name, const struct inode *inode)
 {
@@ -1316,13 +1397,10 @@
 	else {
 		/* FIXME: how much do we care about inodes that have no
 		 * associated name? */
-		if (context->name_count >= AUDIT_NAMES - AUDIT_NAMES_RESERVED)
+		if (audit_inc_name_count(context, inode))
 			return;
-		idx = context->name_count++;
+		idx = context->name_count - 1;
 		context->names[idx].name = NULL;
-#if AUDIT_DEBUG
-		++context->ino_count;
-#endif
 	}
 	audit_copy_inode(&context->names[idx], inode);
 }
@@ -1346,7 +1424,7 @@
 {
 	int idx;
 	struct audit_context *context = current->audit_context;
-	const char *found_name = NULL;
+	const char *found_parent = NULL, *found_child = NULL;
 	int dirlen = 0;
 
 	if (!context->in_syscall)
@@ -1354,88 +1432,73 @@
 
 	/* determine matching parent */
 	if (!dname)
-		goto update_context;
-	for (idx = 0; idx < context->name_count; idx++)
-		if (context->names[idx].ino == parent->i_ino) {
-			const char *name = context->names[idx].name;
+		goto add_names;
 
-			if (!name)
-				continue;
+	/* parent is more likely, look for it first */
+	for (idx = 0; idx < context->name_count; idx++) {
+		struct audit_names *n = &context->names[idx];
 
-			if (audit_compare_dname_path(dname, name, &dirlen) == 0) {
-				context->names[idx].name_len = dirlen;
-				found_name = name;
-				break;
-			}
+		if (!n->name)
+			continue;
+
+		if (n->ino == parent->i_ino &&
+		    !audit_compare_dname_path(dname, n->name, &dirlen)) {
+			n->name_len = dirlen; /* update parent data in place */
+			found_parent = n->name;
+			goto add_names;
 		}
-
-update_context:
-	idx = context->name_count;
-	if (context->name_count == AUDIT_NAMES) {
-		printk(KERN_DEBUG "name_count maxed and losing %s\n",
-			found_name ?: "(null)");
-		return;
 	}
-	context->name_count++;
-#if AUDIT_DEBUG
-	context->ino_count++;
-#endif
-	/* Re-use the name belonging to the slot for a matching parent directory.
-	 * All names for this context are relinquished in audit_free_names() */
-	context->names[idx].name = found_name;
-	context->names[idx].name_len = AUDIT_NAME_FULL;
-	context->names[idx].name_put = 0;	/* don't call __putname() */
 
-	if (!inode)
-		context->names[idx].ino = (unsigned long)-1;
-	else
-		audit_copy_inode(&context->names[idx], inode);
+	/* no matching parent, look for matching child */
+	for (idx = 0; idx < context->name_count; idx++) {
+		struct audit_names *n = &context->names[idx];
 
-	/* A parent was not found in audit_names, so copy the inode data for the
-	 * provided parent. */
-	if (!found_name) {
-		idx = context->name_count;
-		if (context->name_count == AUDIT_NAMES) {
-			printk(KERN_DEBUG
-				"name_count maxed and losing parent inode data: dev=%02x:%02x, inode=%lu",
-				MAJOR(parent->i_sb->s_dev),
-				MINOR(parent->i_sb->s_dev),
-				parent->i_ino);
-			return;
+		if (!n->name)
+			continue;
+
+		/* strcmp() is the more likely scenario */
+		if (!strcmp(dname, n->name) ||
+		     !audit_compare_dname_path(dname, n->name, &dirlen)) {
+			if (inode)
+				audit_copy_inode(n, inode);
+			else
+				n->ino = (unsigned long)-1;
+			found_child = n->name;
+			goto add_names;
 		}
-		context->name_count++;
-#if AUDIT_DEBUG
-		context->ino_count++;
-#endif
+	}
+
+add_names:
+	if (!found_parent) {
+		if (audit_inc_name_count(context, parent))
+			return;
+		idx = context->name_count - 1;
+		context->names[idx].name = NULL;
 		audit_copy_inode(&context->names[idx], parent);
 	}
-}
 
-/**
- * audit_inode_update - update inode info for last collected name
- * @inode: inode being audited
- *
- * When open() is called on an existing object with the O_CREAT flag, the inode
- * data audit initially collects is incorrect.  This additional hook ensures
- * audit has the inode data for the actual object to be opened.
- */
-void __audit_inode_update(const struct inode *inode)
-{
-	struct audit_context *context = current->audit_context;
-	int idx;
+	if (!found_child) {
+		if (audit_inc_name_count(context, inode))
+			return;
+		idx = context->name_count - 1;
 
-	if (!context->in_syscall || !inode)
-		return;
+		/* Re-use the name belonging to the slot for a matching parent
+		 * directory. All names for this context are relinquished in
+		 * audit_free_names() */
+		if (found_parent) {
+			context->names[idx].name = found_parent;
+			context->names[idx].name_len = AUDIT_NAME_FULL;
+			/* don't call __putname() */
+			context->names[idx].name_put = 0;
+		} else {
+			context->names[idx].name = NULL;
+		}
 
-	if (context->name_count == 0) {
-		context->name_count++;
-#if AUDIT_DEBUG
-		context->ino_count++;
-#endif
+		if (inode)
+			audit_copy_inode(&context->names[idx], inode);
+		else
+			context->names[idx].ino = (unsigned long)-1;
 	}
-	idx = context->name_count - 1;
-
-	audit_copy_inode(&context->names[idx], inode);
 }
 
 /**
@@ -1880,6 +1943,14 @@
 	return 0;
 }
 
+void __audit_ptrace(struct task_struct *t)
+{
+	struct audit_context *context = current->audit_context;
+
+	context->target_pid = t->pid;
+	selinux_get_task_sid(t, &context->target_sid);
+}
+
 /**
  * audit_avc_path - record the granting or denial of permissions
  * @dentry: dentry to record
@@ -1918,15 +1989,17 @@
  * If the audit subsystem is being terminated, record the task (pid)
  * and uid that is doing that.
  */
-void __audit_signal_info(int sig, struct task_struct *t)
+int __audit_signal_info(int sig, struct task_struct *t)
 {
+	struct audit_aux_data_pids *axp;
+	struct task_struct *tsk = current;
+	struct audit_context *ctx = tsk->audit_context;
 	extern pid_t audit_sig_pid;
 	extern uid_t audit_sig_uid;
 	extern u32 audit_sig_sid;
 
-	if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
-		struct task_struct *tsk = current;
-		struct audit_context *ctx = tsk->audit_context;
+	if (audit_pid && t->tgid == audit_pid &&
+	    (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1)) {
 		audit_sig_pid = tsk->pid;
 		if (ctx)
 			audit_sig_uid = ctx->loginuid;
@@ -1934,4 +2007,72 @@
 			audit_sig_uid = tsk->uid;
 		selinux_get_task_sid(tsk, &audit_sig_sid);
 	}
+
+	if (!audit_signals) /* audit_context checked in wrapper */
+		return 0;
+
+	/* optimize the common case by putting first signal recipient directly
+	 * in audit_context */
+	if (!ctx->target_pid) {
+		ctx->target_pid = t->tgid;
+		selinux_get_task_sid(t, &ctx->target_sid);
+		return 0;
+	}
+
+	axp = (void *)ctx->aux_pids;
+	if (!axp || axp->pid_count == AUDIT_AUX_PIDS) {
+		axp = kzalloc(sizeof(*axp), GFP_ATOMIC);
+		if (!axp)
+			return -ENOMEM;
+
+		axp->d.type = AUDIT_OBJ_PID;
+		axp->d.next = ctx->aux_pids;
+		ctx->aux_pids = (void *)axp;
+	}
+	BUG_ON(axp->pid_count > AUDIT_AUX_PIDS);
+
+	axp->target_pid[axp->pid_count] = t->tgid;
+	selinux_get_task_sid(t, &axp->target_sid[axp->pid_count]);
+	axp->pid_count++;
+
+	return 0;
+}
+
+/**
+ * audit_core_dumps - record information about processes that end abnormally
+ * @sig: signal value
+ *
+ * If a process ends with a core dump, something fishy is going on and we
+ * should record the event for investigation.
+ */
+void audit_core_dumps(long signr)
+{
+	struct audit_buffer *ab;
+	u32 sid;
+
+	if (!audit_enabled)
+		return;
+
+	if (signr == SIGQUIT)	/* don't care for those */
+		return;
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+	audit_log_format(ab, "auid=%u uid=%u gid=%u",
+			audit_get_loginuid(current->audit_context),
+			current->uid, current->gid);
+	selinux_get_task_sid(current, &sid);
+	if (sid) {
+		char *ctx = NULL;
+		u32 len;
+
+		if (selinux_sid_to_string(sid, &ctx, &len))
+			audit_log_format(ab, " ssid=%u", sid);
+		else
+			audit_log_format(ab, " subj=%s", ctx);
+		kfree(ctx);
+	}
+	audit_log_format(ab, " pid=%d comm=", current->pid);
+	audit_log_untrustedstring(ab, current->comm);
+	audit_log_format(ab, " sig=%ld", signr);
+	audit_log_end(ab);
 }
diff --git a/kernel/compat.c b/kernel/compat.c
index cebb4c2..3bae374 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -475,8 +475,8 @@
 	return min_length;
 }
 
-static int get_compat_itimerspec(struct itimerspec *dst, 
-				 struct compat_itimerspec __user *src)
+int get_compat_itimerspec(struct itimerspec *dst,
+			  const struct compat_itimerspec __user *src)
 { 
 	if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
 	    get_compat_timespec(&dst->it_value, &src->it_value))
@@ -484,8 +484,8 @@
 	return 0;
 } 
 
-static int put_compat_itimerspec(struct compat_itimerspec __user *dst, 
-				 struct itimerspec *src)
+int put_compat_itimerspec(struct compat_itimerspec __user *dst,
+			  const struct itimerspec *src)
 { 
 	if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
 	    put_compat_timespec(&src->it_value, &dst->it_value))
diff --git a/kernel/exit.c b/kernel/exit.c
index b0c6f0c..c6d14b8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -24,6 +24,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/ptrace.h>
 #include <linux/profile.h>
+#include <linux/signalfd.h>
 #include <linux/mount.h>
 #include <linux/proc_fs.h>
 #include <linux/kthread.h>
@@ -42,6 +43,7 @@
 #include <linux/audit.h> /* for audit_free() */
 #include <linux/resource.h>
 #include <linux/blkdev.h>
+#include <linux/task_io_accounting_ops.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -82,6 +84,14 @@
 	sighand = rcu_dereference(tsk->sighand);
 	spin_lock(&sighand->siglock);
 
+	/*
+	 * Notify that this sighand has been detached. This must
+	 * be called with the tsk->sighand lock held. Also, this
+	 * access tsk->sighand internally, so it must be called
+	 * before tsk->sighand is reset.
+	 */
+	signalfd_detach_locked(tsk);
+
 	posix_cpu_timers_exit(tsk);
 	if (atomic_dec_and_test(&sig->count))
 		posix_cpu_timers_exit_group(tsk);
@@ -113,6 +123,8 @@
 		sig->nvcsw += tsk->nvcsw;
 		sig->nivcsw += tsk->nivcsw;
 		sig->sched_time += tsk->sched_time;
+		sig->inblock += task_io_get_inblock(tsk);
+		sig->oublock += task_io_get_oublock(tsk);
 		sig = NULL; /* Marker for below. */
 	}
 
@@ -299,12 +311,12 @@
 	if (process_session(curr) != session) {
 		detach_pid(curr, PIDTYPE_SID);
 		set_signal_session(curr->signal, session);
-		attach_pid(curr, PIDTYPE_SID, session);
+		attach_pid(curr, PIDTYPE_SID, find_pid(session));
 	}
 	if (process_group(curr) != pgrp) {
 		detach_pid(curr, PIDTYPE_PGID);
 		curr->signal->pgrp = pgrp;
-		attach_pid(curr, PIDTYPE_PGID, pgrp);
+		attach_pid(curr, PIDTYPE_PGID, find_pid(pgrp));
 	}
 }
 
@@ -1193,6 +1205,12 @@
 			p->nvcsw + sig->nvcsw + sig->cnvcsw;
 		psig->cnivcsw +=
 			p->nivcsw + sig->nivcsw + sig->cnivcsw;
+		psig->cinblock +=
+			task_io_get_inblock(p) +
+			sig->inblock + sig->cinblock;
+		psig->coublock +=
+			task_io_get_oublock(p) +
+			sig->oublock + sig->coublock;
 		spin_unlock_irq(&p->parent->sighand->siglock);
 	}
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 5dd3979..49530e4 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -875,6 +875,7 @@
 	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
 	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+	sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0;
 	sig->sched_time = 0;
 	INIT_LIST_HEAD(&sig->cpu_timers[0]);
 	INIT_LIST_HEAD(&sig->cpu_timers[1]);
@@ -955,7 +956,7 @@
 					unsigned long stack_size,
 					int __user *parent_tidptr,
 					int __user *child_tidptr,
-					int pid)
+					struct pid *pid)
 {
 	int retval;
 	struct task_struct *p = NULL;
@@ -1022,7 +1023,7 @@
 	p->did_exec = 0;
 	delayacct_tsk_init(p);	/* Must remain after dup_task_struct() */
 	copy_flags(clone_flags, p);
-	p->pid = pid;
+	p->pid = pid_nr(pid);
 	retval = -EFAULT;
 	if (clone_flags & CLONE_PARENT_SETTID)
 		if (put_user(p->pid, parent_tidptr))
@@ -1251,13 +1252,13 @@
 			p->signal->tty = current->signal->tty;
 			p->signal->pgrp = process_group(current);
 			set_signal_session(p->signal, process_session(current));
-			attach_pid(p, PIDTYPE_PGID, process_group(p));
-			attach_pid(p, PIDTYPE_SID, process_session(p));
+			attach_pid(p, PIDTYPE_PGID, task_pgrp(current));
+			attach_pid(p, PIDTYPE_SID, task_session(current));
 
 			list_add_tail_rcu(&p->tasks, &init_task.tasks);
 			__get_cpu_var(process_counts)++;
 		}
-		attach_pid(p, PIDTYPE_PID, p->pid);
+		attach_pid(p, PIDTYPE_PID, pid);
 		nr_threads++;
 	}
 
@@ -1321,7 +1322,8 @@
 	struct task_struct *task;
 	struct pt_regs regs;
 
-	task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0);
+	task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL,
+				&init_struct_pid);
 	if (!IS_ERR(task))
 		init_idle(task, cpu);
 
@@ -1371,7 +1373,7 @@
 			clone_flags |= CLONE_PTRACE;
 	}
 
-	p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, nr);
+	p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr, pid);
 	/*
 	 * Do this prior waking up the new thread - the thread pointer
 	 * might get invalid after that point, if the thread exits quickly.
@@ -1420,12 +1422,15 @@
 #define ARCH_MIN_MMSTRUCT_ALIGN 0
 #endif
 
-static void sighand_ctor(void *data, struct kmem_cache *cachep, unsigned long flags)
+static void sighand_ctor(void *data, struct kmem_cache *cachep,
+			unsigned long flags)
 {
 	struct sighand_struct *sighand = data;
 
-	if (flags & SLAB_CTOR_CONSTRUCTOR)
+	if (flags & SLAB_CTOR_CONSTRUCTOR) {
 		spin_lock_init(&sighand->siglock);
+		INIT_LIST_HEAD(&sighand->signalfd_list);
+	}
 }
 
 void __init proc_caches_init(void)
@@ -1451,7 +1456,6 @@
 			SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 }
 
-
 /*
  * Check constraints on flags passed to the unshare system call and
  * force unsharing of additional process context as appropriate.
diff --git a/kernel/pid.c b/kernel/pid.c
index d3ad724..eb66bd2 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -27,11 +27,13 @@
 #include <linux/bootmem.h>
 #include <linux/hash.h>
 #include <linux/pid_namespace.h>
+#include <linux/init_task.h>
 
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
 static struct hlist_head *pid_hash;
 static int pidhash_shift;
 static struct kmem_cache *pid_cachep;
+struct pid init_struct_pid = INIT_STRUCT_PID;
 
 int pid_max = PID_MAX_DEFAULT;
 
@@ -247,13 +249,16 @@
 }
 EXPORT_SYMBOL_GPL(find_pid);
 
-int fastcall attach_pid(struct task_struct *task, enum pid_type type, int nr)
+/*
+ * attach_pid() must be called with the tasklist_lock write-held.
+ */
+int fastcall attach_pid(struct task_struct *task, enum pid_type type,
+		struct pid *pid)
 {
 	struct pid_link *link;
-	struct pid *pid;
 
 	link = &task->pids[type];
-	link->pid = pid = find_pid(nr);
+	link->pid = pid;
 	hlist_add_head_rcu(&link->node, &pid->tasks[type]);
 
 	return 0;
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4d50e06..ad7949a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -161,6 +162,8 @@
 {
 	int retval;
 
+	audit_ptrace(task);
+
 	retval = -EPERM;
 	if (task->pid <= 1)
 		goto out;
diff --git a/kernel/signal.c b/kernel/signal.c
index 2ac3a66..364fc95 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -21,6 +21,7 @@
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
+#include <linux/signalfd.h>
 #include <linux/capability.h>
 #include <linux/freezer.h>
 #include <linux/pid_namespace.h>
@@ -113,8 +114,7 @@
 
 /* Given the mask, find the first available signal that should be serviced. */
 
-static int
-next_signal(struct sigpending *pending, sigset_t *mask)
+int next_signal(struct sigpending *pending, sigset_t *mask)
 {
 	unsigned long i, *s, *m, x;
 	int sig = 0;
@@ -497,6 +497,11 @@
 	int error = -EINVAL;
 	if (!valid_signal(sig))
 		return error;
+
+	error = audit_signal_info(sig, t); /* Let audit system see the signal */
+	if (error)
+		return error;
+
 	error = -EPERM;
 	if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
 	    && ((sig != SIGCONT) ||
@@ -506,10 +511,7 @@
 	    && !capable(CAP_KILL))
 		return error;
 
-	error = security_task_kill(t, info, sig, 0);
-	if (!error)
-		audit_signal_info(sig, t); /* Let audit system see the signal */
-	return error;
+	return security_task_kill(t, info, sig, 0);
 }
 
 /* forward decl */
@@ -630,6 +632,12 @@
 	int ret = 0;
 
 	/*
+	 * Deliver the signal to listening signalfds. This must be called
+	 * with the sighand lock held.
+	 */
+	signalfd_notify(t, sig);
+
+	/*
 	 * fast-pathed signals for kernel-internal things like SIGSTOP
 	 * or SIGKILL.
 	 */
@@ -1280,6 +1288,11 @@
 		ret = 1;
 		goto out;
 	}
+	/*
+	 * Deliver the signal to listening signalfds. This must be called
+	 * with the sighand lock held.
+	 */
+	signalfd_notify(p, sig);
 
 	list_add_tail(&q->list, &p->pending.list);
 	sigaddset(&p->pending.signal, sig);
@@ -1323,6 +1336,11 @@
 		q->info.si_overrun++;
 		goto out;
 	} 
+	/*
+	 * Deliver the signal to listening signalfds. This must be called
+	 * with the sighand lock held.
+	 */
+	signalfd_notify(p, sig);
 
 	/*
 	 * Put this signal on the shared-pending queue.
@@ -1983,6 +2001,8 @@
 	/*
 	 * If you change siginfo_t structure, please be sure
 	 * this code is fixed accordingly.
+	 * Please remember to update the signalfd_copyinfo() function
+	 * inside fs/signalfd.c too, in case siginfo_t changes.
 	 * It should never copy any pad contained in the structure
 	 * to avoid security leaks, but must copy the generic
 	 * 3 ints plus the relevant union member.
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index daabb74..fcee2a8 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -8,6 +8,8 @@
 #include <linux/sched.h>
 #include <linux/stop_machine.h>
 #include <linux/syscalls.h>
+#include <linux/interrupt.h>
+
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/uaccess.h>
@@ -45,6 +47,7 @@
 		if (stopmachine_state == STOPMACHINE_DISABLE_IRQ 
 		    && !irqs_disabled) {
 			local_irq_disable();
+			hard_irq_disable();
 			irqs_disabled = 1;
 			/* Ack: irqs disabled. */
 			smp_mb(); /* Must read state first. */
@@ -124,6 +127,7 @@
 
 	/* Make them disable irqs. */
 	local_irq_disable();
+	hard_irq_disable();
 	stopmachine_set_state(STOPMACHINE_DISABLE_IRQ);
 
 	return 0;
diff --git a/kernel/sys.c b/kernel/sys.c
index cdb7e94..872271c 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -14,6 +14,7 @@
 #include <linux/prctl.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/resource.h>
 #include <linux/kernel.h>
 #include <linux/kexec.h>
 #include <linux/workqueue.h>
@@ -29,6 +30,7 @@
 #include <linux/signal.h>
 #include <linux/cn_proc.h>
 #include <linux/getcpu.h>
+#include <linux/task_io_accounting_ops.h>
 
 #include <linux/compat.h>
 #include <linux/syscalls.h>
@@ -658,7 +660,7 @@
 	int error = -EINVAL;
 	struct pid *pgrp;
 
-	if (which > 2 || which < 0)
+	if (which > PRIO_USER || which < PRIO_PROCESS)
 		goto out;
 
 	/* normalize: avoid signed division (rounding problems) */
@@ -722,7 +724,7 @@
 	long niceval, retval = -ESRCH;
 	struct pid *pgrp;
 
-	if (which > 2 || which < 0)
+	if (which > PRIO_USER || which < PRIO_PROCESS)
 		return -EINVAL;
 
 	read_lock(&tasklist_lock);
@@ -1486,7 +1488,7 @@
 	if (process_group(p) != pgid) {
 		detach_pid(p, PIDTYPE_PGID);
 		p->signal->pgrp = pgid;
-		attach_pid(p, PIDTYPE_PGID, pgid);
+		attach_pid(p, PIDTYPE_PGID, find_pid(pgid));
 	}
 
 	err = 0;
@@ -2082,6 +2084,8 @@
 			r->ru_nivcsw = p->signal->cnivcsw;
 			r->ru_minflt = p->signal->cmin_flt;
 			r->ru_majflt = p->signal->cmaj_flt;
+			r->ru_inblock = p->signal->cinblock;
+			r->ru_oublock = p->signal->coublock;
 
 			if (who == RUSAGE_CHILDREN)
 				break;
@@ -2093,6 +2097,8 @@
 			r->ru_nivcsw += p->signal->nivcsw;
 			r->ru_minflt += p->signal->min_flt;
 			r->ru_majflt += p->signal->maj_flt;
+			r->ru_inblock += p->signal->inblock;
+			r->ru_oublock += p->signal->oublock;
 			t = p;
 			do {
 				utime = cputime_add(utime, t->utime);
@@ -2101,6 +2107,8 @@
 				r->ru_nivcsw += t->nivcsw;
 				r->ru_minflt += t->min_flt;
 				r->ru_majflt += t->maj_flt;
+				r->ru_inblock += task_io_get_inblock(t);
+				r->ru_oublock += task_io_get_oublock(t);
 				t = next_thread(t);
 			} while (t != p);
 			break;
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index d7306d0..b6d77a8 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -141,3 +141,8 @@
 cond_syscall(sys_bdflush);
 cond_syscall(sys_ioprio_set);
 cond_syscall(sys_ioprio_get);
+
+/* New file descriptors */
+cond_syscall(sys_signalfd);
+cond_syscall(sys_timerfd);
+cond_syscall(sys_eventfd);
diff --git a/kernel/timer.c b/kernel/timer.c
index 59a28b1..a6c580a 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -92,24 +92,24 @@
 /* Functions below help us manage 'deferrable' flag */
 static inline unsigned int tbase_get_deferrable(tvec_base_t *base)
 {
-	return (unsigned int)((unsigned long)base & TBASE_DEFERRABLE_FLAG);
+	return ((unsigned int)(unsigned long)base & TBASE_DEFERRABLE_FLAG);
 }
 
 static inline tvec_base_t *tbase_get_base(tvec_base_t *base)
 {
-	return (tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG);
+	return ((tvec_base_t *)((unsigned long)base & ~TBASE_DEFERRABLE_FLAG));
 }
 
 static inline void timer_set_deferrable(struct timer_list *timer)
 {
-	timer->base = (tvec_base_t *)((unsigned long)timer->base |
-	                               TBASE_DEFERRABLE_FLAG);
+	timer->base = ((tvec_base_t *)((unsigned long)(timer->base) |
+	                               TBASE_DEFERRABLE_FLAG));
 }
 
 static inline void
 timer_set_base(struct timer_list *timer, tvec_base_t *new_base)
 {
-	timer->base = (tvec_base_t *)((unsigned long)new_base |
+	timer->base = (tvec_base_t *)((unsigned long)(new_base) |
 	                              tbase_get_deferrable(timer->base));
 }
 
diff --git a/lib/Kconfig b/lib/Kconfig
index 96d6e8c..2e7ae6b 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -23,6 +23,14 @@
 	  the kernel tree does. Such modules that use library CRC16
 	  functions require M here.
 
+config CRC_ITU_T
+	tristate "CRC ITU-T V.41 functions"
+	help
+	  This option is provided for the case where no in-kernel-tree
+	  modules require CRC ITU-T V.41 functions, but a module built outside
+	  the kernel tree does. Such modules that use library CRC ITU-T V.41
+	  functions require M here.
+
 config CRC32
 	tristate "CRC32 functions"
 	default y
diff --git a/lib/Makefile b/lib/Makefile
index ae57f35..c8c8e20 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -13,7 +13,7 @@
 lib-y	+= kobject.o kref.o kobject_uevent.o klist.o
 
 obj-y += div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
-	 bust_spinlocks.o
+	 bust_spinlocks.o hexdump.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
@@ -41,6 +41,7 @@
 obj-$(CONFIG_BITREVERSE) += bitrev.o
 obj-$(CONFIG_CRC_CCITT)	+= crc-ccitt.o
 obj-$(CONFIG_CRC16)	+= crc16.o
+obj-$(CONFIG_CRC_ITU_T)	+= crc-itu-t.o
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
 obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
diff --git a/lib/audit.c b/lib/audit.c
index 3b1289f..8e7dc1c 100644
--- a/lib/audit.c
+++ b/lib/audit.c
@@ -23,6 +23,16 @@
 ~0U
 };
 
+static unsigned signal_class[] = {
+#include <asm-generic/audit_signal.h>
+~0U
+};
+
+int audit_classify_arch(int arch)
+{
+	return 0;
+}
+
 int audit_classify_syscall(int abi, unsigned syscall)
 {
 	switch(syscall) {
@@ -49,6 +59,7 @@
 	audit_register_class(AUDIT_CLASS_READ, read_class);
 	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
 	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	audit_register_class(AUDIT_CLASS_SIGNAL, signal_class);
 	return 0;
 }
 
diff --git a/lib/crc-itu-t.c b/lib/crc-itu-t.c
new file mode 100644
index 0000000..a63472b
--- /dev/null
+++ b/lib/crc-itu-t.c
@@ -0,0 +1,69 @@
+/*
+ *      crc-itu-t.c
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/crc-itu-t.h>
+
+/** CRC table for the CRC ITU-T V.41 0x0x1021 (x^16 + x^12 + x^15 + 1) */
+const u16 crc_itu_t_table[256] = {
+	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+	0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+	0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+	0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+	0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+	0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+	0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+	0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+	0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+	0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+	0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+	0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+	0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+	0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+	0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+	0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+	0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+	0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+	0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+	0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+	0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+	0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+	0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+	0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+	0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+	0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+	0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+	0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+	0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+	0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+	0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+	0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+};
+
+EXPORT_SYMBOL(crc_itu_t_table);
+
+/**
+ * crc_itu_t - Compute the CRC-ITU-T for the data buffer
+ *
+ * @crc:     previous CRC value
+ * @buffer:  data pointer
+ * @len:     number of bytes in the buffer
+ *
+ * Returns the updated CRC value
+ */
+u16 crc_itu_t(u16 crc, const u8 *buffer, size_t len)
+{
+	while (len--)
+		crc = crc_itu_t_byte(crc, *buffer++);
+	return crc;
+}
+EXPORT_SYMBOL(crc_itu_t);
+
+MODULE_DESCRIPTION("CRC ITU-T V.41 calculations");
+MODULE_LICENSE("GPL");
+
diff --git a/lib/hexdump.c b/lib/hexdump.c
new file mode 100644
index 0000000..e6da5b7
--- /dev/null
+++ b/lib/hexdump.c
@@ -0,0 +1,104 @@
+/*
+ * lib/hexdump.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+/**
+ * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ * @linebuf: where to put the converted data
+ * @linebuflen: total size of @linebuf, including space for terminating NUL
+ *
+ * hex_dump_to_buffer() works on one "line" of output at a time, i.e.,
+ * 16 bytes of input data converted to hex + ASCII output.
+ *
+ * Given a buffer of u8 data, hex_dump_to_buffer() converts the input data
+ * to a hex + ASCII dump at the supplied memory location.
+ * The converted output is always NUL-terminated.
+ *
+ * E.g.:
+ *	hex_dump_to_buffer(frame->data, frame->len, linebuf, sizeof(linebuf));
+ *
+ * example output buffer:
+ * 40414243 44454647 48494a4b 4c4d4e4f  @ABCDEFGHIJKLMNO
+ */
+void hex_dump_to_buffer(const void *buf, size_t len, char *linebuf,
+			size_t linebuflen)
+{
+	const u8 *ptr = buf;
+	u8 ch;
+	int j, lx = 0;
+
+	for (j = 0; (j < 16) && (j < len) && (lx + 3) < linebuflen; j++) {
+		if (j && !(j % 4))
+			linebuf[lx++] = ' ';
+		ch = ptr[j];
+		linebuf[lx++] = hex_asc(ch >> 4);
+		linebuf[lx++] = hex_asc(ch & 0x0f);
+	}
+	if ((lx + 2) < linebuflen) {
+		linebuf[lx++] = ' ';
+		linebuf[lx++] = ' ';
+	}
+	for (j = 0; (j < 16) && (j < len) && (lx + 2) < linebuflen; j++)
+		linebuf[lx++] = isprint(ptr[j]) ? ptr[j] : '.';
+	linebuf[lx++] = '\0';
+}
+EXPORT_SYMBOL(hex_dump_to_buffer);
+
+/**
+ * print_hex_dump - print a text hex dump to syslog for a binary blob of data
+ * @level: kernel log level (e.g. KERN_DEBUG)
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Given a buffer of u8 data, print_hex_dump() prints a hex + ASCII dump
+ * to the kernel log at the specified kernel log level, with an optional
+ * leading prefix.
+ *
+ * E.g.:
+ *   print_hex_dump(KERN_DEBUG, DUMP_PREFIX_ADDRESS, frame->data, frame->len);
+ *
+ * Example output using %DUMP_PREFIX_OFFSET:
+ * 0009ab42: 40414243 44454647 48494a4b 4c4d4e4f  @ABCDEFGHIJKLMNO
+ * Example output using %DUMP_PREFIX_ADDRESS:
+ * ffffffff88089af0: 70717273 74757677 78797a7b 7c7d7e7f  pqrstuvwxyz{|}~.
+ */
+void print_hex_dump(const char *level, int prefix_type, void *buf, size_t len)
+{
+	u8 *ptr = buf;
+	int i, linelen, remaining = len;
+	unsigned char linebuf[100];
+
+	for (i = 0; i < len; i += 16) {
+		linelen = min(remaining, 16);
+		remaining -= 16;
+		hex_dump_to_buffer(ptr + i, linelen, linebuf, sizeof(linebuf));
+
+		switch (prefix_type) {
+		case DUMP_PREFIX_ADDRESS:
+			printk("%s%*p: %s\n", level,
+				(int)(2 * sizeof(void *)), ptr + i, linebuf);
+			break;
+		case DUMP_PREFIX_OFFSET:
+			printk("%s%.8x: %s\n", level, i, linebuf);
+			break;
+		default:
+			printk("%s%s\n", level, linebuf);
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL(print_hex_dump);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 63cd888..eec1481 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -588,31 +588,27 @@
 }
 
 /**
- * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them.
+ * write_cache_pages - walk the list of dirty pages of the given address space and write all of them.
  * @mapping: address space structure to write
  * @wbc: subtract the number of written pages from *@wbc->nr_to_write
+ * @writepage: function called for each page
+ * @data: data passed to writepage function
  *
- * This is a library function, which implements the writepages()
- * address_space_operation.
- *
- * If a page is already under I/O, generic_writepages() skips it, even
+ * If a page is already under I/O, write_cache_pages() skips it, even
  * if it's dirty.  This is desirable behaviour for memory-cleaning writeback,
  * but it is INCORRECT for data-integrity system calls such as fsync().  fsync()
  * and msync() need to guarantee that all the data which was dirty at the time
  * the call was made get new I/O started against them.  If wbc->sync_mode is
  * WB_SYNC_ALL then we were called for data integrity and we must wait for
  * existing IO to complete.
- *
- * Derived from mpage_writepages() - if you fix this you should check that
- * also!
  */
-int generic_writepages(struct address_space *mapping,
-		       struct writeback_control *wbc)
+int write_cache_pages(struct address_space *mapping,
+		      struct writeback_control *wbc, writepage_t writepage,
+		      void *data)
 {
 	struct backing_dev_info *bdi = mapping->backing_dev_info;
 	int ret = 0;
 	int done = 0;
-	int (*writepage)(struct page *page, struct writeback_control *wbc);
 	struct pagevec pvec;
 	int nr_pages;
 	pgoff_t index;
@@ -625,12 +621,6 @@
 		return 0;
 	}
 
-	writepage = mapping->a_ops->writepage;
-
-	/* deal with chardevs and other special file */
-	if (!writepage)
-		return 0;
-
 	pagevec_init(&pvec, 0);
 	if (wbc->range_cyclic) {
 		index = mapping->writeback_index; /* Start from prev offset */
@@ -682,8 +672,7 @@
 				continue;
 			}
 
-			ret = (*writepage)(page, wbc);
-			mapping_set_error(mapping, ret);
+			ret = (*writepage)(page, wbc, data);
 
 			if (unlikely(ret == AOP_WRITEPAGE_ACTIVATE))
 				unlock_page(page);
@@ -710,6 +699,38 @@
 		mapping->writeback_index = index;
 	return ret;
 }
+EXPORT_SYMBOL(write_cache_pages);
+
+/*
+ * Function used by generic_writepages to call the real writepage
+ * function and set the mapping flags on error
+ */
+static int __writepage(struct page *page, struct writeback_control *wbc,
+		       void *data)
+{
+	struct address_space *mapping = data;
+	int ret = mapping->a_ops->writepage(page, wbc);
+	mapping_set_error(mapping, ret);
+	return ret;
+}
+
+/**
+ * generic_writepages - walk the list of dirty pages of the given address space and writepage() all of them.
+ * @mapping: address space structure to write
+ * @wbc: subtract the number of written pages from *@wbc->nr_to_write
+ *
+ * This is a library function, which implements the writepages()
+ * address_space_operation.
+ */
+int generic_writepages(struct address_space *mapping,
+		       struct writeback_control *wbc)
+{
+	/* deal with chardevs and other special file */
+	if (!mapping->a_ops->writepage)
+		return 0;
+
+	return write_cache_pages(mapping, wbc, __writepage, mapping);
+}
 
 EXPORT_SYMBOL(generic_writepages);
 
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index f9b5d6d..ae96dd8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2284,7 +2284,7 @@
  * was used and there are no special requirements, this is a convenient
  * alternative
  */
-int __init early_pfn_to_nid(unsigned long pfn)
+int __meminit early_pfn_to_nid(unsigned long pfn)
 {
 	int i;
 
diff --git a/mm/slub.c b/mm/slub.c
index bd2efae..b39c8a6 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -81,10 +81,14 @@
  * PageActive 		The slab is used as a cpu cache. Allocations
  * 			may be performed from the slab. The slab is not
  * 			on any slab list and cannot be moved onto one.
+ * 			The cpu slab may be equipped with an additioanl
+ * 			lockless_freelist that allows lockless access to
+ * 			free objects in addition to the regular freelist
+ * 			that requires the slab lock.
  *
  * PageError		Slab requires special handling due to debug
  * 			options set. This moves	slab handling out of
- * 			the fast path.
+ * 			the fast path and disables lockless freelists.
  */
 
 static inline int SlabDebug(struct page *page)
@@ -1014,6 +1018,7 @@
 	set_freepointer(s, last, NULL);
 
 	page->freelist = start;
+	page->lockless_freelist = NULL;
 	page->inuse = 0;
 out:
 	if (flags & __GFP_WAIT)
@@ -1276,6 +1281,23 @@
  */
 static void deactivate_slab(struct kmem_cache *s, struct page *page, int cpu)
 {
+	/*
+	 * Merge cpu freelist into freelist. Typically we get here
+	 * because both freelists are empty. So this is unlikely
+	 * to occur.
+	 */
+	while (unlikely(page->lockless_freelist)) {
+		void **object;
+
+		/* Retrieve object from cpu_freelist */
+		object = page->lockless_freelist;
+		page->lockless_freelist = page->lockless_freelist[page->offset];
+
+		/* And put onto the regular freelist */
+		object[page->offset] = page->freelist;
+		page->freelist = object;
+		page->inuse--;
+	}
 	s->cpu_slab[cpu] = NULL;
 	ClearPageActive(page);
 
@@ -1322,47 +1344,46 @@
 }
 
 /*
- * slab_alloc is optimized to only modify two cachelines on the fast path
- * (aside from the stack):
+ * Slow path. The lockless freelist is empty or we need to perform
+ * debugging duties.
  *
- * 1. The page struct
- * 2. The first cacheline of the object to be allocated.
+ * Interrupts are disabled.
  *
- * The only other cache lines that are read (apart from code) is the
- * per cpu array in the kmem_cache struct.
+ * Processing is still very fast if new objects have been freed to the
+ * regular freelist. In that case we simply take over the regular freelist
+ * as the lockless freelist and zap the regular freelist.
  *
- * Fastpath is not possible if we need to get a new slab or have
- * debugging enabled (which means all slabs are marked with SlabDebug)
+ * If that is not working then we fall back to the partial lists. We take the
+ * first element of the freelist as the object to allocate now and move the
+ * rest of the freelist to the lockless freelist.
+ *
+ * And if we were unable to get a new slab from the partial slab lists then
+ * we need to allocate a new slab. This is slowest path since we may sleep.
  */
-static void *slab_alloc(struct kmem_cache *s,
-				gfp_t gfpflags, int node, void *addr)
+static void *__slab_alloc(struct kmem_cache *s,
+		gfp_t gfpflags, int node, void *addr, struct page *page)
 {
-	struct page *page;
 	void **object;
-	unsigned long flags;
-	int cpu;
+	int cpu = smp_processor_id();
 
-	local_irq_save(flags);
-	cpu = smp_processor_id();
-	page = s->cpu_slab[cpu];
 	if (!page)
 		goto new_slab;
 
 	slab_lock(page);
 	if (unlikely(node != -1 && page_to_nid(page) != node))
 		goto another_slab;
-redo:
+load_freelist:
 	object = page->freelist;
 	if (unlikely(!object))
 		goto another_slab;
 	if (unlikely(SlabDebug(page)))
 		goto debug;
 
-have_object:
-	page->inuse++;
-	page->freelist = object[page->offset];
+	object = page->freelist;
+	page->lockless_freelist = object[page->offset];
+	page->inuse = s->objects;
+	page->freelist = NULL;
 	slab_unlock(page);
-	local_irq_restore(flags);
 	return object;
 
 another_slab:
@@ -1370,11 +1391,11 @@
 
 new_slab:
 	page = get_partial(s, gfpflags, node);
-	if (likely(page)) {
+	if (page) {
 have_slab:
 		s->cpu_slab[cpu] = page;
 		SetPageActive(page);
-		goto redo;
+		goto load_freelist;
 	}
 
 	page = new_slab(s, gfpflags, node);
@@ -1397,7 +1418,7 @@
 				discard_slab(s, page);
 				page = s->cpu_slab[cpu];
 				slab_lock(page);
-				goto redo;
+				goto load_freelist;
 			}
 			/* New slab does not fit our expectations */
 			flush_slab(s, s->cpu_slab[cpu], cpu);
@@ -1405,16 +1426,52 @@
 		slab_lock(page);
 		goto have_slab;
 	}
-	local_irq_restore(flags);
 	return NULL;
 debug:
+	object = page->freelist;
 	if (!alloc_object_checks(s, page, object))
 		goto another_slab;
 	if (s->flags & SLAB_STORE_USER)
 		set_track(s, object, TRACK_ALLOC, addr);
 	trace(s, page, object, 1);
 	init_object(s, object, 1);
-	goto have_object;
+
+	page->inuse++;
+	page->freelist = object[page->offset];
+	slab_unlock(page);
+	return object;
+}
+
+/*
+ * Inlined fastpath so that allocation functions (kmalloc, kmem_cache_alloc)
+ * have the fastpath folded into their functions. So no function call
+ * overhead for requests that can be satisfied on the fastpath.
+ *
+ * The fastpath works by first checking if the lockless freelist can be used.
+ * If not then __slab_alloc is called for slow processing.
+ *
+ * Otherwise we can simply pick the next object from the lockless free list.
+ */
+static void __always_inline *slab_alloc(struct kmem_cache *s,
+				gfp_t gfpflags, int node, void *addr)
+{
+	struct page *page;
+	void **object;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	page = s->cpu_slab[smp_processor_id()];
+	if (unlikely(!page || !page->lockless_freelist ||
+			(node != -1 && page_to_nid(page) != node)))
+
+		object = __slab_alloc(s, gfpflags, node, addr, page);
+
+	else {
+		object = page->lockless_freelist;
+		page->lockless_freelist = object[page->offset];
+	}
+	local_irq_restore(flags);
+	return object;
 }
 
 void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags)
@@ -1432,20 +1489,19 @@
 #endif
 
 /*
- * The fastpath only writes the cacheline of the page struct and the first
- * cacheline of the object.
+ * Slow patch handling. This may still be called frequently since objects
+ * have a longer lifetime than the cpu slabs in most processing loads.
  *
- * We read the cpu_slab cacheline to check if the slab is the per cpu
- * slab for this processor.
+ * So we still attempt to reduce cache line usage. Just take the slab
+ * lock and free the item. If there is no additional partial page
+ * handling required then we can return immediately.
  */
-static void slab_free(struct kmem_cache *s, struct page *page,
+static void __slab_free(struct kmem_cache *s, struct page *page,
 					void *x, void *addr)
 {
 	void *prior;
 	void **object = (void *)x;
-	unsigned long flags;
 
-	local_irq_save(flags);
 	slab_lock(page);
 
 	if (unlikely(SlabDebug(page)))
@@ -1475,7 +1531,6 @@
 
 out_unlock:
 	slab_unlock(page);
-	local_irq_restore(flags);
 	return;
 
 slab_empty:
@@ -1487,7 +1542,6 @@
 
 	slab_unlock(page);
 	discard_slab(s, page);
-	local_irq_restore(flags);
 	return;
 
 debug:
@@ -1502,6 +1556,34 @@
 	goto checks_ok;
 }
 
+/*
+ * Fastpath with forced inlining to produce a kfree and kmem_cache_free that
+ * can perform fastpath freeing without additional function calls.
+ *
+ * The fastpath is only possible if we are freeing to the current cpu slab
+ * of this processor. This typically the case if we have just allocated
+ * the item before.
+ *
+ * If fastpath is not possible then fall back to __slab_free where we deal
+ * with all sorts of special processing.
+ */
+static void __always_inline slab_free(struct kmem_cache *s,
+			struct page *page, void *x, void *addr)
+{
+	void **object = (void *)x;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	if (likely(page == s->cpu_slab[smp_processor_id()] &&
+						!SlabDebug(page))) {
+		object[page->offset] = page->lockless_freelist;
+		page->lockless_freelist = object;
+	} else
+		__slab_free(s, page, x, addr);
+
+	local_irq_restore(flags);
+}
+
 void kmem_cache_free(struct kmem_cache *s, void *x)
 {
 	struct page *page;
@@ -2363,9 +2445,8 @@
 	register_cpu_notifier(&slab_notifier);
 #endif
 
-	if (nr_cpu_ids)	/* Remove when nr_cpu_ids is fixed upstream ! */
-		kmem_size = offsetof(struct kmem_cache, cpu_slab)
-			 + nr_cpu_ids * sizeof(struct page *);
+	kmem_size = offsetof(struct kmem_cache, cpu_slab) +
+				nr_cpu_ids * sizeof(struct page *);
 
 	printk(KERN_INFO "SLUB: Genslabs=%d, HWalign=%d, Order=%d-%d, MinObjects=%d,"
 		" Processors=%d, Nodes=%d\n",
diff --git a/mm/thrash.c b/mm/thrash.c
index 9ef9071..c4c5205 100644
--- a/mm/thrash.c
+++ b/mm/thrash.c
@@ -48,9 +48,8 @@
 		if (current_interval < current->mm->last_interval)
 			current->mm->token_priority++;
 		else {
-			current->mm->token_priority--;
-			if (unlikely(current->mm->token_priority < 0))
-				current->mm->token_priority = 0;
+			if (likely(current->mm->token_priority > 0))
+				current->mm->token_priority--;
 		}
 		/* Check if we deserve the token */
 		if (current->mm->token_priority >
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 9832d9a..8faf27e 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -698,7 +698,7 @@
 {
 	struct delayed_work *vmstat_work = &per_cpu(vmstat_work, cpu);
 
-	INIT_DELAYED_WORK(vmstat_work, vmstat_update);
+	INIT_DELAYED_WORK_DEFERRABLE(vmstat_work, vmstat_update);
 	schedule_delayed_work_on(cpu, vmstat_work, HZ + cpu);
 }
 
diff --git a/net/Kconfig b/net/Kconfig
index caeacd1..f3de729 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -218,6 +218,7 @@
 	bool
 
 menu "Wireless"
+	depends on !S390
 
 source "net/wireless/Kconfig"
 source "net/mac80211/Kconfig"
diff --git a/net/ax25/Kconfig b/net/ax25/Kconfig
index 43dd86f..2a72aa9 100644
--- a/net/ax25/Kconfig
+++ b/net/ax25/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig HAMRADIO
-	depends on NET
+	depends on NET && !S390
 	bool "Amateur Radio support"
 	help
 	  If you want to connect your Linux box to an amateur radio, answer Y
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index 6929490..7725da9 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig BT
-	depends on NET
+	depends on NET && !S390
 	tristate "Bluetooth subsystem support"
 	help
 	  Bluetooth is low-cost, low-power, short-range wireless technology.
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index d342e89..ceadfcf 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -174,7 +174,7 @@
 
 static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct hid_device *hid = dev->private;
+	struct hid_device *hid = input_get_drvdata(dev);
 	struct hidp_session *session = hid->driver_data;
 
 	return hidp_queue_event(session, dev, type, code, value);
@@ -182,7 +182,7 @@
 
 static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
-	struct hidp_session *session = dev->private;
+	struct hidp_session *session = input_get_drvdata(dev);
 
 	return hidp_queue_event(session, dev, type, code, value);
 }
@@ -630,7 +630,7 @@
 	struct input_dev *input = session->input;
 	int i;
 
-	input->private = session;
+	input_set_drvdata(input, session);
 
 	input->name = "Bluetooth HID Boot Protocol Device";
 
@@ -663,7 +663,7 @@
 		input->relbit[0] |= BIT(REL_WHEEL);
 	}
 
-	input->cdev.dev = hidp_get_device(session);
+	input->dev.parent = hidp_get_device(session);
 
 	input->event = hidp_input_event;
 
@@ -737,10 +737,8 @@
 	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
 		hidp_send_report(session, report);
 
-	if (hidinput_connect(hid) == 0) {
+	if (hidinput_connect(hid) == 0)
 		hid->claimed |= HID_CLAIMED_INPUT;
-		hid_ff_init(hid);
-	}
 }
 
 int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
@@ -864,7 +862,7 @@
 	if (session->hid)
 		hid_free_device(session->hid);
 
-	kfree(session->input);
+	input_free_device(session->input);
 	kfree(session);
 	return err;
 }
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index e3c26a9..a5e372b 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -19,7 +19,6 @@
 #include <linux/rtnetlink.h>
 #include <linux/jiffies.h>
 #include <linux/spinlock.h>
-#include <linux/list.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
@@ -27,8 +26,7 @@
 
 
 enum lw_bits {
-	LW_RUNNING = 0,
-	LW_SE_USED
+	LW_URGENT = 0,
 };
 
 static unsigned long linkwatch_flags;
@@ -37,17 +35,9 @@
 static void linkwatch_event(struct work_struct *dummy);
 static DECLARE_DELAYED_WORK(linkwatch_work, linkwatch_event);
 
-static LIST_HEAD(lweventlist);
+static struct net_device *lweventlist;
 static DEFINE_SPINLOCK(lweventlist_lock);
 
-struct lw_event {
-	struct list_head list;
-	struct net_device *dev;
-};
-
-/* Avoid kmalloc() for most systems */
-static struct lw_event singleevent;
-
 static unsigned char default_operstate(const struct net_device *dev)
 {
 	if (!netif_carrier_ok(dev))
@@ -87,25 +77,102 @@
 }
 
 
-/* Must be called with the rtnl semaphore held */
-void linkwatch_run_queue(void)
+static int linkwatch_urgent_event(struct net_device *dev)
 {
-	struct list_head head, *n, *next;
+	return netif_running(dev) && netif_carrier_ok(dev) &&
+	       dev->qdisc != dev->qdisc_sleeping;
+}
+
+
+static void linkwatch_add_event(struct net_device *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&lweventlist_lock, flags);
+	dev->link_watch_next = lweventlist;
+	lweventlist = dev;
+	spin_unlock_irqrestore(&lweventlist_lock, flags);
+}
+
+
+static void linkwatch_schedule_work(int urgent)
+{
+	unsigned long delay = linkwatch_nextevent - jiffies;
+
+	if (test_bit(LW_URGENT, &linkwatch_flags))
+		return;
+
+	/* Minimise down-time: drop delay for up event. */
+	if (urgent) {
+		if (test_and_set_bit(LW_URGENT, &linkwatch_flags))
+			return;
+		delay = 0;
+	}
+
+	/* If we wrap around we'll delay it by at most HZ. */
+	if (delay > HZ)
+		delay = 0;
+
+	/*
+	 * This is true if we've scheduled it immeditately or if we don't
+	 * need an immediate execution and it's already pending.
+	 */
+	if (schedule_delayed_work(&linkwatch_work, delay) == !delay)
+		return;
+
+	/* Don't bother if there is nothing urgent. */
+	if (!test_bit(LW_URGENT, &linkwatch_flags))
+		return;
+
+	/* It's already running which is good enough. */
+	if (!cancel_delayed_work(&linkwatch_work))
+		return;
+
+	/* Otherwise we reschedule it again for immediate exection. */
+	schedule_delayed_work(&linkwatch_work, 0);
+}
+
+
+static void __linkwatch_run_queue(int urgent_only)
+{
+	struct net_device *next;
+
+	/*
+	 * Limit the number of linkwatch events to one
+	 * per second so that a runaway driver does not
+	 * cause a storm of messages on the netlink
+	 * socket.  This limit does not apply to up events
+	 * while the device qdisc is down.
+	 */
+	if (!urgent_only)
+		linkwatch_nextevent = jiffies + HZ;
+	/* Limit wrap-around effect on delay. */
+	else if (time_after(linkwatch_nextevent, jiffies + HZ))
+		linkwatch_nextevent = jiffies;
+
+	clear_bit(LW_URGENT, &linkwatch_flags);
 
 	spin_lock_irq(&lweventlist_lock);
-	list_replace_init(&lweventlist, &head);
+	next = lweventlist;
+	lweventlist = NULL;
 	spin_unlock_irq(&lweventlist_lock);
 
-	list_for_each_safe(n, next, &head) {
-		struct lw_event *event = list_entry(n, struct lw_event, list);
-		struct net_device *dev = event->dev;
+	while (next) {
+		struct net_device *dev = next;
 
-		if (event == &singleevent) {
-			clear_bit(LW_SE_USED, &linkwatch_flags);
-		} else {
-			kfree(event);
+		next = dev->link_watch_next;
+
+		if (urgent_only && !linkwatch_urgent_event(dev)) {
+			linkwatch_add_event(dev);
+			continue;
 		}
 
+		/*
+		 * Make sure the above read is complete since it can be
+		 * rewritten as soon as we clear the bit below.
+		 */
+		smp_mb__before_clear_bit();
+
 		/* We are about to handle this device,
 		 * so new events can be accepted
 		 */
@@ -124,58 +191,39 @@
 
 		dev_put(dev);
 	}
+
+	if (lweventlist)
+		linkwatch_schedule_work(0);
+}
+
+
+/* Must be called with the rtnl semaphore held */
+void linkwatch_run_queue(void)
+{
+	__linkwatch_run_queue(0);
 }
 
 
 static void linkwatch_event(struct work_struct *dummy)
 {
-	/* Limit the number of linkwatch events to one
-	 * per second so that a runaway driver does not
-	 * cause a storm of messages on the netlink
-	 * socket
-	 */
-	linkwatch_nextevent = jiffies + HZ;
-	clear_bit(LW_RUNNING, &linkwatch_flags);
-
 	rtnl_lock();
-	linkwatch_run_queue();
+	__linkwatch_run_queue(time_after(linkwatch_nextevent, jiffies));
 	rtnl_unlock();
 }
 
 
 void linkwatch_fire_event(struct net_device *dev)
 {
+	int urgent = linkwatch_urgent_event(dev);
+
 	if (!test_and_set_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state)) {
-		unsigned long flags;
-		struct lw_event *event;
-
-		if (test_and_set_bit(LW_SE_USED, &linkwatch_flags)) {
-			event = kmalloc(sizeof(struct lw_event), GFP_ATOMIC);
-
-			if (unlikely(event == NULL)) {
-				clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
-				return;
-			}
-		} else {
-			event = &singleevent;
-		}
-
 		dev_hold(dev);
-		event->dev = dev;
 
-		spin_lock_irqsave(&lweventlist_lock, flags);
-		list_add_tail(&event->list, &lweventlist);
-		spin_unlock_irqrestore(&lweventlist_lock, flags);
+		linkwatch_add_event(dev);
+	} else if (!urgent)
+		return;
 
-		if (!test_and_set_bit(LW_RUNNING, &linkwatch_flags)) {
-			unsigned long delay = linkwatch_nextevent - jiffies;
-
-			/* If we wrap around we'll delay it by at most HZ. */
-			if (delay > HZ)
-				delay = 0;
-			schedule_delayed_work(&linkwatch_work, delay);
-		}
-	}
+	linkwatch_schedule_work(urgent);
 }
 
 EXPORT_SYMBOL(linkwatch_fire_event);
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 7edea2a..75c0230 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -15,128 +15,34 @@
 #define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
 			   (1 << NF_ARP_FORWARD))
 
-/* Standard entry. */
-struct arpt_standard
-{
-	struct arpt_entry entry;
-	struct arpt_standard_target target;
-};
-
-struct arpt_error_target
-{
-	struct arpt_entry_target target;
-	char errorname[ARPT_FUNCTION_MAXNAMELEN];
-};
-
-struct arpt_error
-{
-	struct arpt_entry entry;
-	struct arpt_error_target target;
-};
-
 static struct
 {
 	struct arpt_replace repl;
 	struct arpt_standard entries[3];
 	struct arpt_error term;
-} initial_table __initdata
-= { { "filter", FILTER_VALID_HOOKS, 4,
-      sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
-      { [NF_ARP_IN] = 0,
-	[NF_ARP_OUT] = sizeof(struct arpt_standard),
-	[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), },
-      { [NF_ARP_IN] = 0,
-	[NF_ARP_OUT] = sizeof(struct arpt_standard),
-	[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard), },
-      0, NULL, { } },
-    {
-	    /* ARP_IN */
-	    {
-		    {
-			    {
-				    { 0 }, { 0 }, { 0 }, { 0 },
-				    0, 0,
-				    { { 0, }, { 0, } },
-				    { { 0, }, { 0, } },
-				    0, 0,
-				    0, 0,
-				    0, 0,
-				    "", "", { 0 }, { 0 },
-				    0, 0
-			    },
-			    sizeof(struct arpt_entry),
-			    sizeof(struct arpt_standard),
-			    0,
-			    { 0, 0 }, { } },
-		    { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
-		      -NF_ACCEPT - 1 }
-	    },
-	    /* ARP_OUT */
-	    {
-		    {
-			    {
-				    { 0 }, { 0 }, { 0 }, { 0 },
-				    0, 0,
-				    { { 0, }, { 0, } },
-				    { { 0, }, { 0, } },
-				    0, 0,
-				    0, 0,
-				    0, 0,
-				    "", "", { 0 }, { 0 },
-				    0, 0
-			    },
-			    sizeof(struct arpt_entry),
-			    sizeof(struct arpt_standard),
-			    0,
-			    { 0, 0 }, { } },
-		    { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
-		      -NF_ACCEPT - 1 }
-	    },
-	    /* ARP_FORWARD */
-	    {
-		    {
-			    {
-				    { 0 }, { 0 }, { 0 }, { 0 },
-				    0, 0,
-				    { { 0, }, { 0, } },
-				    { { 0, }, { 0, } },
-				    0, 0,
-				    0, 0,
-				    0, 0,
-				    "", "", { 0 }, { 0 },
-				    0, 0
-			    },
-			    sizeof(struct arpt_entry),
-			    sizeof(struct arpt_standard),
-			    0,
-			    { 0, 0 }, { } },
-		    { { { { ARPT_ALIGN(sizeof(struct arpt_standard_target)), "" } }, { } },
-		      -NF_ACCEPT - 1 }
-	    }
-    },
-    /* ERROR */
-    {
-	    {
-		    {
-			    { 0 }, { 0 }, { 0 }, { 0 },
-			    0, 0,
-			    { { 0, }, { 0, } },
-			    { { 0, }, { 0, } },
-			    0, 0,
-			    0, 0,
-			    0, 0,
-			    "", "", { 0 }, { 0 },
-			    0, 0
-		    },
-		    sizeof(struct arpt_entry),
-		    sizeof(struct arpt_error),
-		    0,
-		    { 0, 0 }, { } },
-	    { { { { ARPT_ALIGN(sizeof(struct arpt_error_target)), ARPT_ERROR_TARGET } },
-		{ } },
-	      "ERROR"
-	    }
-    }
+} initial_table __initdata = {
+	.repl = {
+		.name = "filter",
+		.valid_hooks = FILTER_VALID_HOOKS,
+		.num_entries = 4,
+		.size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
+		.hook_entry = {
+			[NF_ARP_IN] = 0,
+			[NF_ARP_OUT] = sizeof(struct arpt_standard),
+			[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
+		},
+		.underflow = {
+			[NF_ARP_IN] = 0,
+			[NF_ARP_OUT] = sizeof(struct arpt_standard),
+			[NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
+		},
+	},
+	.entries = {
+		ARPT_STANDARD_INIT(NF_ACCEPT),	/* ARP_IN */
+		ARPT_STANDARD_INIT(NF_ACCEPT),	/* ARP_OUT */
+		ARPT_STANDARD_INIT(NF_ACCEPT),	/* ARP_FORWARD */
+	},
+	.term = ARPT_ERROR_INIT,
 };
 
 static struct arpt_table packet_filter = {
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index 4272890..4f51c1d 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -26,53 +26,29 @@
 	struct ipt_replace repl;
 	struct ipt_standard entries[3];
 	struct ipt_error term;
-} initial_table __initdata
-= { { "filter", FILTER_VALID_HOOKS, 4,
-      sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
-      { [NF_IP_LOCAL_IN] = 0,
-	[NF_IP_FORWARD] = sizeof(struct ipt_standard),
-	[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
-      { [NF_IP_LOCAL_IN] = 0,
-	[NF_IP_FORWARD] = sizeof(struct ipt_standard),
-	[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
-      0, NULL, { } },
-    {
-	    /* LOCAL_IN */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* FORWARD */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_OUT */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } }
-    },
-    /* ERROR */
-    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-	0,
-	sizeof(struct ipt_entry),
-	sizeof(struct ipt_error),
-	0, { 0, 0 }, { } },
-      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
-	  { } },
-	"ERROR"
-      }
-    }
+} initial_table __initdata = {
+	.repl = {
+		.name = "filter",
+		.valid_hooks = FILTER_VALID_HOOKS,
+		.num_entries = 4,
+		.size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
+		.hook_entry = {
+			[NF_IP_LOCAL_IN] = 0,
+			[NF_IP_FORWARD] = sizeof(struct ipt_standard),
+			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
+		},
+		.underflow = {
+			[NF_IP_LOCAL_IN] = 0,
+			[NF_IP_FORWARD] = sizeof(struct ipt_standard),
+			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
+		},
+	},
+	.entries = {
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_IN */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* FORWARD */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
+	},
+	.term = IPT_ERROR_INIT,			/* ERROR */
 };
 
 static struct xt_table packet_filter = {
@@ -105,7 +81,8 @@
 	if ((*pskb)->len < sizeof(struct iphdr)
 	    || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
 		if (net_ratelimit())
-			printk("ipt_hook: happy cracking.\n");
+			printk("iptable_filter: ignoring short SOCK_RAW "
+			       "packet.\n");
 		return NF_ACCEPT;
 	}
 
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index 9278802..902446f 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -33,73 +33,35 @@
 	struct ipt_replace repl;
 	struct ipt_standard entries[5];
 	struct ipt_error term;
-} initial_table __initdata
-= { { "mangle", MANGLE_VALID_HOOKS, 6,
-      sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
-      { [NF_IP_PRE_ROUTING] 	= 0,
-	[NF_IP_LOCAL_IN] 	= sizeof(struct ipt_standard),
-	[NF_IP_FORWARD] 	= sizeof(struct ipt_standard) * 2,
-	[NF_IP_LOCAL_OUT] 	= sizeof(struct ipt_standard) * 3,
-	[NF_IP_POST_ROUTING] 	= sizeof(struct ipt_standard) * 4 },
-      { [NF_IP_PRE_ROUTING] 	= 0,
-	[NF_IP_LOCAL_IN] 	= sizeof(struct ipt_standard),
-	[NF_IP_FORWARD] 	= sizeof(struct ipt_standard) * 2,
-	[NF_IP_LOCAL_OUT] 	= sizeof(struct ipt_standard) * 3,
-	[NF_IP_POST_ROUTING]	= sizeof(struct ipt_standard) * 4 },
-      0, NULL, { } },
-    {
-	    /* PRE_ROUTING */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_IN */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* FORWARD */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_OUT */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* POST_ROUTING */
-	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ipt_entry),
-		sizeof(struct ipt_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-    },
-    /* ERROR */
-    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-	0,
-	sizeof(struct ipt_entry),
-	sizeof(struct ipt_error),
-	0, { 0, 0 }, { } },
-      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
-	  { } },
-	"ERROR"
-      }
-    }
+} initial_table __initdata = {
+	.repl = {
+		.name = "mangle",
+		.valid_hooks = MANGLE_VALID_HOOKS,
+		.num_entries = 6,
+		.size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
+		.hook_entry = {
+			[NF_IP_PRE_ROUTING] 	= 0,
+			[NF_IP_LOCAL_IN] 	= sizeof(struct ipt_standard),
+			[NF_IP_FORWARD] 	= sizeof(struct ipt_standard) * 2,
+			[NF_IP_LOCAL_OUT] 	= sizeof(struct ipt_standard) * 3,
+			[NF_IP_POST_ROUTING] 	= sizeof(struct ipt_standard) * 4,
+		},
+		.underflow = {
+			[NF_IP_PRE_ROUTING] 	= 0,
+			[NF_IP_LOCAL_IN] 	= sizeof(struct ipt_standard),
+			[NF_IP_FORWARD] 	= sizeof(struct ipt_standard) * 2,
+			[NF_IP_LOCAL_OUT] 	= sizeof(struct ipt_standard) * 3,
+			[NF_IP_POST_ROUTING]	= sizeof(struct ipt_standard) * 4,
+		},
+	},
+	.entries = {
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* PRE_ROUTING */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_IN */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* FORWARD */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* POST_ROUTING */
+	},
+	.term = IPT_ERROR_INIT,			/* ERROR */
 };
 
 static struct xt_table packet_mangler = {
@@ -138,7 +100,8 @@
 	if ((*pskb)->len < sizeof(struct iphdr)
 	    || ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
 		if (net_ratelimit())
-			printk("ipt_hook: happy cracking.\n");
+			printk("iptable_mangle: ignoring short SOCK_RAW "
+			       "packet.\n");
 		return NF_ACCEPT;
 	}
 
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 18c3d4c..d6e5033 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -5,6 +5,7 @@
  */
 #include <linux/module.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
+#include <net/ip.h>
 
 #define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
 
@@ -21,62 +22,18 @@
 		.size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
 		.hook_entry = {
 			[NF_IP_PRE_ROUTING] = 0,
-			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) },
+			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard)
+		},
 		.underflow = {
 			[NF_IP_PRE_ROUTING] = 0,
-			[NF_IP_LOCAL_OUT]  = sizeof(struct ipt_standard) },
+			[NF_IP_LOCAL_OUT]  = sizeof(struct ipt_standard)
+		},
 	},
 	.entries = {
-	     /* PRE_ROUTING */
-	     {
-		     .entry = {
-			     .target_offset = sizeof(struct ipt_entry),
-			     .next_offset = sizeof(struct ipt_standard),
-		     },
-		     .target = {
-			  .target = {
-				  .u = {
-					  .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
-				  },
-			  },
-			  .verdict = -NF_ACCEPT - 1,
-		     },
-	     },
-
-	     /* LOCAL_OUT */
-	     {
-		     .entry = {
-			     .target_offset = sizeof(struct ipt_entry),
-			     .next_offset = sizeof(struct ipt_standard),
-		     },
-		     .target = {
-			     .target = {
-				     .u = {
-					     .target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
-				     },
-			     },
-			     .verdict = -NF_ACCEPT - 1,
-		     },
-	     },
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* PRE_ROUTING */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
 	},
-	/* ERROR */
-	.term = {
-		.entry = {
-			.target_offset = sizeof(struct ipt_entry),
-			.next_offset = sizeof(struct ipt_error),
-		},
-		.target = {
-			.target = {
-				.u = {
-					.user = {
-						.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
-						.name = IPT_ERROR_TARGET,
-					},
-				},
-			},
-			.errorname = "ERROR",
-		},
-	}
+	.term = IPT_ERROR_INIT,			/* ERROR */
 };
 
 static struct xt_table packet_raw = {
@@ -98,6 +55,24 @@
 	return ipt_do_table(pskb, hook, in, out, &packet_raw);
 }
 
+static unsigned int
+ipt_local_hook(unsigned int hook,
+	       struct sk_buff **pskb,
+	       const struct net_device *in,
+	       const struct net_device *out,
+	       int (*okfn)(struct sk_buff *))
+{
+	/* root is playing with raw sockets. */
+	if ((*pskb)->len < sizeof(struct iphdr) ||
+	    ip_hdrlen(*pskb) < sizeof(struct iphdr)) {
+		if (net_ratelimit())
+			printk("iptable_raw: ignoring short SOCK_RAW"
+			       "packet.\n");
+		return NF_ACCEPT;
+	}
+	return ipt_do_table(pskb, hook, in, out, &packet_raw);
+}
+
 /* 'raw' is the very first table. */
 static struct nf_hook_ops ipt_ops[] = {
 	{
@@ -108,7 +83,7 @@
 		.owner = THIS_MODULE,
 	},
 	{
-		.hook = ipt_hook,
+		.hook = ipt_local_hook,
 		.pf = PF_INET,
 		.hooknum = NF_IP_LOCAL_OUT,
 		.priority = NF_IP_PRI_RAW,
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 2534f71..6740736 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -46,77 +46,20 @@
 		.hook_entry = {
 			[NF_IP_PRE_ROUTING] = 0,
 			[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
-			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
+			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
+		},
 		.underflow = {
 			[NF_IP_PRE_ROUTING] = 0,
 			[NF_IP_POST_ROUTING] = sizeof(struct ipt_standard),
-			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2 },
+			[NF_IP_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
+		},
 	},
 	.entries = {
-		/* PRE_ROUTING */
-		{
-			.entry = {
-				.target_offset = sizeof(struct ipt_entry),
-				.next_offset = sizeof(struct ipt_standard),
-			},
-			.target = {
-				.target = {
-					.u = {
-						.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
-					},
-				},
-				.verdict = -NF_ACCEPT - 1,
-			},
-		},
-		/* POST_ROUTING */
-		{
-			.entry = {
-				.target_offset = sizeof(struct ipt_entry),
-				.next_offset = sizeof(struct ipt_standard),
-			},
-			.target = {
-				.target = {
-					.u = {
-						.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
-					},
-				},
-				.verdict = -NF_ACCEPT - 1,
-			},
-		},
-		/* LOCAL_OUT */
-		{
-			.entry = {
-				.target_offset = sizeof(struct ipt_entry),
-				.next_offset = sizeof(struct ipt_standard),
-			},
-			.target = {
-				.target = {
-					.u = {
-						.target_size = IPT_ALIGN(sizeof(struct ipt_standard_target)),
-					},
-				},
-				.verdict = -NF_ACCEPT - 1,
-			},
-		},
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* PRE_ROUTING */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* POST_ROUTING */
+		IPT_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
 	},
-	/* ERROR */
-	.term = {
-		.entry = {
-			.target_offset = sizeof(struct ipt_entry),
-			.next_offset = sizeof(struct ipt_error),
-		},
-		.target = {
-			.target = {
-				.u = {
-					.user = {
-						.target_size = IPT_ALIGN(sizeof(struct ipt_error_target)),
-						.name = IPT_ERROR_TARGET,
-					},
-				},
-			},
-			.errorname = "ERROR",
-		},
-	}
+	.term = IPT_ERROR_INIT,			/* ERROR */
 };
 
 static struct xt_table nat_table = {
@@ -230,9 +173,7 @@
 }
 
 inline unsigned int
-alloc_null_binding(struct nf_conn *ct,
-		   struct nf_nat_info *info,
-		   unsigned int hooknum)
+alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
 {
 	/* Force range to this IP; let proto decide mapping for
 	   per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
@@ -251,9 +192,7 @@
 }
 
 unsigned int
-alloc_null_binding_confirmed(struct nf_conn *ct,
-			     struct nf_nat_info *info,
-			     unsigned int hooknum)
+alloc_null_binding_confirmed(struct nf_conn *ct, unsigned int hooknum)
 {
 	__be32 ip
 		= (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
@@ -275,8 +214,7 @@
 		     unsigned int hooknum,
 		     const struct net_device *in,
 		     const struct net_device *out,
-		     struct nf_conn *ct,
-		     struct nf_nat_info *info)
+		     struct nf_conn *ct)
 {
 	int ret;
 
@@ -285,7 +223,7 @@
 	if (ret == NF_ACCEPT) {
 		if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
 			/* NUL mapping */
-			ret = alloc_null_binding(ct, info, hooknum);
+			ret = alloc_null_binding(ct, hooknum);
 	}
 	return ret;
 }
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c
index 64bbed2..55dac36 100644
--- a/net/ipv4/netfilter/nf_nat_standalone.c
+++ b/net/ipv4/netfilter/nf_nat_standalone.c
@@ -80,7 +80,6 @@
 	struct nf_conn *ct;
 	enum ip_conntrack_info ctinfo;
 	struct nf_conn_nat *nat;
-	struct nf_nat_info *info;
 	/* maniptype == SRC for postrouting. */
 	enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
 
@@ -129,7 +128,6 @@
 		}
 		/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
 	case IP_CT_NEW:
-		info = &nat->info;
 
 		/* Seen it before?  This can happen for loopback, retrans,
 		   or local packets.. */
@@ -138,14 +136,13 @@
 
 			if (unlikely(nf_ct_is_confirmed(ct)))
 				/* NAT module was loaded late */
-				ret = alloc_null_binding_confirmed(ct, info,
-								   hooknum);
+				ret = alloc_null_binding_confirmed(ct, hooknum);
 			else if (hooknum == NF_IP_LOCAL_IN)
 				/* LOCAL_IN hook doesn't have a chain!  */
-				ret = alloc_null_binding(ct, info, hooknum);
+				ret = alloc_null_binding(ct, hooknum);
 			else
 				ret = nf_nat_rule_find(pskb, hooknum, in, out,
-						       ct, info);
+						       ct);
 
 			if (ret != NF_ACCEPT) {
 				return ret;
@@ -160,10 +157,8 @@
 		/* ESTABLISHED */
 		NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
 			     ctinfo == (IP_CT_ESTABLISHED+IP_CT_IS_REPLY));
-		info = &nat->info;
 	}
 
-	NF_CT_ASSERT(info);
 	return nf_nat_packet(ct, ctinfo, hooknum, pskb);
 }
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 66026df..4c7e95f 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -118,15 +118,15 @@
  * Note about this hash function :
  * Typical use is probably daddr = 0, only dport is going to vary hash
  */
-static inline unsigned int hash_port_and_addr(__u16 port, __be32 addr)
+static inline unsigned int udp_hash_port(__u16 port)
 {
-	addr ^= addr >> 16;
-	addr ^= addr >> 8;
-	return port ^ addr;
+	return port;
 }
 
 static inline int __udp_lib_port_inuse(unsigned int hash, int port,
-	__be32 daddr, struct hlist_head udptable[])
+				       const struct sock *this_sk,
+				       struct hlist_head udptable[],
+				       const struct udp_get_port_ops *ops)
 {
 	struct sock *sk;
 	struct hlist_node *node;
@@ -138,7 +138,10 @@
 		inet = inet_sk(sk);
 		if (inet->num != port)
 			continue;
-		if (inet->rcv_saddr == daddr)
+		if (this_sk) {
+			if (ops->saddr_cmp(sk, this_sk))
+				return 1;
+		} else if (ops->saddr_any(sk))
 			return 1;
 	}
 	return 0;
@@ -151,12 +154,11 @@
  *  @snum:        port number to look up
  *  @udptable:    hash list table, must be of UDP_HTABLE_SIZE
  *  @port_rover:  pointer to record of last unallocated port
- *  @saddr_comp:  AF-dependent comparison of bound local IP addresses
+ *  @ops:         AF-dependent address operations
  */
 int __udp_lib_get_port(struct sock *sk, unsigned short snum,
 		       struct hlist_head udptable[], int *port_rover,
-		       int (*saddr_comp)(const struct sock *sk1,
-					 const struct sock *sk2 )    )
+		       const struct udp_get_port_ops *ops)
 {
 	struct hlist_node *node;
 	struct hlist_head *head;
@@ -176,8 +178,7 @@
 		for (i = 0; i < UDP_HTABLE_SIZE; i++, result++) {
 			int size;
 
-			hash = hash_port_and_addr(result,
-					inet_sk(sk)->rcv_saddr);
+			hash = ops->hash_port_and_rcv_saddr(result, sk);
 			head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
 			if (hlist_empty(head)) {
 				if (result > sysctl_local_port_range[1])
@@ -203,17 +204,16 @@
 				result = sysctl_local_port_range[0]
 					+ ((result - sysctl_local_port_range[0]) &
 					   (UDP_HTABLE_SIZE - 1));
-			hash = hash_port_and_addr(result, 0);
+			hash = udp_hash_port(result);
 			if (__udp_lib_port_inuse(hash, result,
-						 0, udptable))
+						 NULL, udptable, ops))
 				continue;
-			if (!inet_sk(sk)->rcv_saddr)
+			if (ops->saddr_any(sk))
 				break;
 
-			hash = hash_port_and_addr(result,
-					inet_sk(sk)->rcv_saddr);
+			hash = ops->hash_port_and_rcv_saddr(result, sk);
 			if (! __udp_lib_port_inuse(hash, result,
-				inet_sk(sk)->rcv_saddr, udptable))
+						   sk, udptable, ops))
 				break;
 		}
 		if (i >= (1 << 16) / UDP_HTABLE_SIZE)
@@ -221,7 +221,7 @@
 gotit:
 		*port_rover = snum = result;
 	} else {
-		hash = hash_port_and_addr(snum, 0);
+		hash = udp_hash_port(snum);
 		head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
 
 		sk_for_each(sk2, node, head)
@@ -231,12 +231,11 @@
 			    (!sk2->sk_reuse || !sk->sk_reuse) &&
 			    (!sk2->sk_bound_dev_if || !sk->sk_bound_dev_if ||
 			     sk2->sk_bound_dev_if == sk->sk_bound_dev_if) &&
-			    (*saddr_comp)(sk, sk2))
+			    ops->saddr_cmp(sk, sk2))
 				goto fail;
 
-		if (inet_sk(sk)->rcv_saddr) {
-			hash = hash_port_and_addr(snum,
-						  inet_sk(sk)->rcv_saddr);
+		if (!ops->saddr_any(sk)) {
+			hash = ops->hash_port_and_rcv_saddr(snum, sk);
 			head = &udptable[hash & (UDP_HTABLE_SIZE - 1)];
 
 			sk_for_each(sk2, node, head)
@@ -248,7 +247,7 @@
 				     !sk->sk_bound_dev_if ||
 				     sk2->sk_bound_dev_if ==
 				     sk->sk_bound_dev_if) &&
-				    (*saddr_comp)(sk, sk2))
+				    ops->saddr_cmp(sk, sk2))
 					goto fail;
 		}
 	}
@@ -266,12 +265,12 @@
 }
 
 int udp_get_port(struct sock *sk, unsigned short snum,
-			int (*scmp)(const struct sock *, const struct sock *))
+		 const struct udp_get_port_ops *ops)
 {
-	return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, scmp);
+	return  __udp_lib_get_port(sk, snum, udp_hash, &udp_port_rover, ops);
 }
 
-int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
+static int ipv4_rcv_saddr_equal(const struct sock *sk1, const struct sock *sk2)
 {
 	struct inet_sock *inet1 = inet_sk(sk1), *inet2 = inet_sk(sk2);
 
@@ -280,9 +279,33 @@
 		   inet1->rcv_saddr == inet2->rcv_saddr      ));
 }
 
+static int ipv4_rcv_saddr_any(const struct sock *sk)
+{
+	return !inet_sk(sk)->rcv_saddr;
+}
+
+static inline unsigned int ipv4_hash_port_and_addr(__u16 port, __be32 addr)
+{
+	addr ^= addr >> 16;
+	addr ^= addr >> 8;
+	return port ^ addr;
+}
+
+static unsigned int ipv4_hash_port_and_rcv_saddr(__u16 port,
+						 const struct sock *sk)
+{
+	return ipv4_hash_port_and_addr(port, inet_sk(sk)->rcv_saddr);
+}
+
+const struct udp_get_port_ops udp_ipv4_ops = {
+	.saddr_cmp = ipv4_rcv_saddr_equal,
+	.saddr_any = ipv4_rcv_saddr_any,
+	.hash_port_and_rcv_saddr = ipv4_hash_port_and_rcv_saddr,
+};
+
 static inline int udp_v4_get_port(struct sock *sk, unsigned short snum)
 {
-	return udp_get_port(sk, snum, ipv4_rcv_saddr_equal);
+	return udp_get_port(sk, snum, &udp_ipv4_ops);
 }
 
 /* UDP is nearly always wildcards out the wazoo, it makes no sense to try
@@ -297,8 +320,8 @@
 	unsigned int hash, hashwild;
 	int score, best = -1, hport = ntohs(dport);
 
- 	hash = hash_port_and_addr(hport, daddr);
- 	hashwild = hash_port_and_addr(hport, 0);
+	hash = ipv4_hash_port_and_addr(hport, daddr);
+	hashwild = udp_hash_port(hport);
 
 	read_lock(&udp_hash_lock);
 
@@ -1198,8 +1221,8 @@
 	struct sock *sk, *skw, *sknext;
 	int dif;
 	int hport = ntohs(uh->dest);
-	unsigned int hash = hash_port_and_addr(hport, daddr);
-	unsigned int hashwild = hash_port_and_addr(hport, 0);
+	unsigned int hash = ipv4_hash_port_and_addr(hport, daddr);
+	unsigned int hashwild = udp_hash_port(hport);
 
 	dif = skb->dev->ifindex;
 
diff --git a/net/ipv4/udp_impl.h b/net/ipv4/udp_impl.h
index 820a477..06d9419 100644
--- a/net/ipv4/udp_impl.h
+++ b/net/ipv4/udp_impl.h
@@ -5,14 +5,14 @@
 #include <net/protocol.h>
 #include <net/inet_common.h>
 
+extern const struct udp_get_port_ops udp_ipv4_ops;
+
 extern int  	__udp4_lib_rcv(struct sk_buff *, struct hlist_head [], int );
 extern void 	__udp4_lib_err(struct sk_buff *, u32, struct hlist_head []);
 
 extern int	__udp_lib_get_port(struct sock *sk, unsigned short snum,
 				   struct hlist_head udptable[], int *port_rover,
-				   int (*)(const struct sock*,const struct sock*));
-extern int	ipv4_rcv_saddr_equal(const struct sock *, const struct sock *);
-
+				   const struct udp_get_port_ops *ops);
 
 extern int	udp_setsockopt(struct sock *sk, int level, int optname,
 			       char __user *optval, int optlen);
diff --git a/net/ipv4/udplite.c b/net/ipv4/udplite.c
index f34fd68..3653b32 100644
--- a/net/ipv4/udplite.c
+++ b/net/ipv4/udplite.c
@@ -19,14 +19,15 @@
 static int		udplite_port_rover;
 
 int udplite_get_port(struct sock *sk, unsigned short p,
-		     int (*c)(const struct sock *, const struct sock *))
+		     const struct udp_get_port_ops *ops)
 {
-	return  __udp_lib_get_port(sk, p, udplite_hash, &udplite_port_rover, c);
+	return  __udp_lib_get_port(sk, p, udplite_hash,
+				   &udplite_port_rover, ops);
 }
 
 static int udplite_v4_get_port(struct sock *sk, unsigned short snum)
 {
-	return udplite_get_port(sk, snum, ipv4_rcv_saddr_equal);
+	return udplite_get_port(sk, snum, &udp_ipv4_ops);
 }
 
 static int udplite_rcv(struct sk_buff *skb)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d02685c..c7ea248 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4204,6 +4204,10 @@
 		return err;
 
 	ip6_null_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+	ip6_prohibit_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+	ip6_blk_hole_entry.rt6i_idev = in6_dev_get(&loopback_dev);
+#endif
 
 	register_netdevice_notifier(&ipv6_dev_notf);
 
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
index 6d8e4ac..14be0b9 100644
--- a/net/ipv6/exthdrs.c
+++ b/net/ipv6/exthdrs.c
@@ -660,6 +660,14 @@
   Hop-by-hop options.
  **********************************/
 
+/*
+ * Note: we cannot rely on skb->dst before we assign it in ip6_route_input().
+ */
+static inline struct inet6_dev *ipv6_skb_idev(struct sk_buff *skb)
+{
+	return skb->dst ? ip6_dst_idev(skb->dst) : __in6_dev_get(skb->dev);
+}
+
 /* Router Alert as of RFC 2711 */
 
 static int ipv6_hop_ra(struct sk_buff **skbp, int optoff)
@@ -688,25 +696,25 @@
 	if (nh[optoff + 1] != 4 || (optoff & 3) != 2) {
 		LIMIT_NETDEBUG(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n",
 			       nh[optoff+1]);
-		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst),
+		IP6_INC_STATS_BH(ipv6_skb_idev(skb),
 				 IPSTATS_MIB_INHDRERRORS);
 		goto drop;
 	}
 
 	pkt_len = ntohl(*(__be32 *)(nh + optoff + 2));
 	if (pkt_len <= IPV6_MAXPLEN) {
-		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+		IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);
 		return 0;
 	}
 	if (ipv6_hdr(skb)->payload_len) {
-		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INHDRERRORS);
+		IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INHDRERRORS);
 		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);
 		return 0;
 	}
 
 	if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {
-		IP6_INC_STATS_BH(ip6_dst_idev(skb->dst), IPSTATS_MIB_INTRUNCATEDPKTS);
+		IP6_INC_STATS_BH(ipv6_skb_idev(skb), IPSTATS_MIB_INTRUNCATEDPKTS);
 		goto drop;
 	}
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f508171..4704b5f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -463,10 +463,17 @@
 		 */
 		if (xrlim_allow(dst, 1*HZ))
 			ndisc_send_redirect(skb, n, target);
-	} else if (ipv6_addr_type(&hdr->saddr)&(IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK
-						|IPV6_ADDR_LINKLOCAL)) {
+	} else {
+		int addrtype = ipv6_addr_type(&hdr->saddr);
+
 		/* This check is security critical. */
-		goto error;
+		if (addrtype & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LOOPBACK))
+			goto error;
+		if (addrtype & IPV6_ADDR_LINKLOCAL) {
+			icmpv6_send(skb, ICMPV6_DEST_UNREACH,
+				ICMPV6_NOT_NEIGHBOUR, 0, skb->dev);
+			goto error;
+		}
 	}
 
 	if (skb->len > dst_mtu(dst)) {
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index 76f0cf6..7e32e2a 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -24,53 +24,29 @@
 	struct ip6t_replace repl;
 	struct ip6t_standard entries[3];
 	struct ip6t_error term;
-} initial_table __initdata
-= { { "filter", FILTER_VALID_HOOKS, 4,
-      sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
-      { [NF_IP6_LOCAL_IN] = 0,
-	[NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
-	[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 },
-      { [NF_IP6_LOCAL_IN] = 0,
-	[NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
-	[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2 },
-      0, NULL, { } },
-    {
-	    /* LOCAL_IN */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* FORWARD */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_OUT */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } }
-    },
-    /* ERROR */
-    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-	0,
-	sizeof(struct ip6t_entry),
-	sizeof(struct ip6t_error),
-	0, { 0, 0 }, { } },
-      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
-	  { } },
-	"ERROR"
-      }
-    }
+} initial_table __initdata = {
+	.repl = {
+		.name = "filter",
+		.valid_hooks = FILTER_VALID_HOOKS,
+		.num_entries = 4,
+		.size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
+		.hook_entry = {
+			[NF_IP6_LOCAL_IN] = 0,
+			[NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
+			[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
+		},
+		.underflow = {
+			[NF_IP6_LOCAL_IN] = 0,
+			[NF_IP6_FORWARD] = sizeof(struct ip6t_standard),
+			[NF_IP6_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
+		},
+	},
+	.entries = {
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_IN */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* FORWARD */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
+	},
+	.term = IP6T_ERROR_INIT,		/* ERROR */
 };
 
 static struct xt_table packet_filter = {
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index a9f10e3..f2d2649 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -32,73 +32,35 @@
 	struct ip6t_replace repl;
 	struct ip6t_standard entries[5];
 	struct ip6t_error term;
-} initial_table __initdata
-= { { "mangle", MANGLE_VALID_HOOKS, 6,
-      sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
-      { [NF_IP6_PRE_ROUTING] 	= 0,
-	[NF_IP6_LOCAL_IN]	= sizeof(struct ip6t_standard),
-	[NF_IP6_FORWARD]	= sizeof(struct ip6t_standard) * 2,
-	[NF_IP6_LOCAL_OUT] 	= sizeof(struct ip6t_standard) * 3,
-	[NF_IP6_POST_ROUTING]	= sizeof(struct ip6t_standard) * 4},
-      { [NF_IP6_PRE_ROUTING] 	= 0,
-	[NF_IP6_LOCAL_IN]	= sizeof(struct ip6t_standard),
-	[NF_IP6_FORWARD]	= sizeof(struct ip6t_standard) * 2,
-	[NF_IP6_LOCAL_OUT] 	= sizeof(struct ip6t_standard) * 3,
-	[NF_IP6_POST_ROUTING]	= sizeof(struct ip6t_standard) * 4},
-      0, NULL, { } },
-    {
-	    /* PRE_ROUTING */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_IN */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* FORWARD */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* LOCAL_OUT */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } },
-	    /* POST_ROUTING */
-	    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-		0,
-		sizeof(struct ip6t_entry),
-		sizeof(struct ip6t_standard),
-		0, { 0, 0 }, { } },
-	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
-		-NF_ACCEPT - 1 } }
-    },
-    /* ERROR */
-    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
-	0,
-	sizeof(struct ip6t_entry),
-	sizeof(struct ip6t_error),
-	0, { 0, 0 }, { } },
-      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
-	  { } },
-	"ERROR"
-      }
-    }
+} initial_table __initdata = {
+	.repl = {
+		.name = "mangle",
+		.valid_hooks = MANGLE_VALID_HOOKS,
+		.num_entries = 6,
+		.size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
+		.hook_entry = {
+			[NF_IP6_PRE_ROUTING] 	= 0,
+			[NF_IP6_LOCAL_IN]	= sizeof(struct ip6t_standard),
+			[NF_IP6_FORWARD]	= sizeof(struct ip6t_standard) * 2,
+			[NF_IP6_LOCAL_OUT] 	= sizeof(struct ip6t_standard) * 3,
+			[NF_IP6_POST_ROUTING]	= sizeof(struct ip6t_standard) * 4,
+		},
+		.underflow = {
+			[NF_IP6_PRE_ROUTING] 	= 0,
+			[NF_IP6_LOCAL_IN]	= sizeof(struct ip6t_standard),
+			[NF_IP6_FORWARD]	= sizeof(struct ip6t_standard) * 2,
+			[NF_IP6_LOCAL_OUT] 	= sizeof(struct ip6t_standard) * 3,
+			[NF_IP6_POST_ROUTING]	= sizeof(struct ip6t_standard) * 4,
+		},
+	},
+	.entries = {
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* PRE_ROUTING */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_IN */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* FORWARD */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* POST_ROUTING */
+	},
+	.term = IP6T_ERROR_INIT,		/* ERROR */
 };
 
 static struct xt_table packet_mangler = {
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index a3eb5b8..0acda45 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -35,56 +35,10 @@
 		},
 	},
 	.entries = {
-		/* PRE_ROUTING */
-		{
-			.entry = {
-				.target_offset = sizeof(struct ip6t_entry),
-				.next_offset = sizeof(struct ip6t_standard),
-			},
-			.target = {
-				.target = {
-					.u = {
-						.target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
-					},
-				},
-				.verdict = -NF_ACCEPT - 1,
-			},
-		},
-
-		/* LOCAL_OUT */
-		{
-			.entry = {
-				.target_offset = sizeof(struct ip6t_entry),
-				.next_offset = sizeof(struct ip6t_standard),
-			},
-			.target = {
-				.target = {
-					.u = {
-						.target_size = IP6T_ALIGN(sizeof(struct ip6t_standard_target)),
-					},
-				},
-				.verdict = -NF_ACCEPT - 1,
-			},
-		},
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* PRE_ROUTING */
+		IP6T_STANDARD_INIT(NF_ACCEPT),	/* LOCAL_OUT */
 	},
-	/* ERROR */
-	.term = {
-		.entry = {
-			.target_offset = sizeof(struct ip6t_entry),
-			.next_offset = sizeof(struct ip6t_error),
-		},
-		.target = {
-			.target = {
-				.u = {
-					.user = {
-						.target_size = IP6T_ALIGN(sizeof(struct ip6t_error_target)),
-						.name = IP6T_ERROR_TARGET,
-					},
-				},
-			},
-			.errorname = "ERROR",
-		},
-	}
+	.term = IP6T_ERROR_INIT,		/* ERROR */
 };
 
 static struct xt_table packet_raw = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index b083c09..a7ae59c 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -52,9 +52,28 @@
 
 DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6) __read_mostly;
 
+static int ipv6_rcv_saddr_any(const struct sock *sk)
+{
+	struct ipv6_pinfo *np = inet6_sk(sk);
+
+	return ipv6_addr_any(&np->rcv_saddr);
+}
+
+static unsigned int ipv6_hash_port_and_rcv_saddr(__u16 port,
+						 const struct sock *sk)
+{
+	return port;
+}
+
+const struct udp_get_port_ops udp_ipv6_ops = {
+	.saddr_cmp = ipv6_rcv_saddr_equal,
+	.saddr_any = ipv6_rcv_saddr_any,
+	.hash_port_and_rcv_saddr = ipv6_hash_port_and_rcv_saddr,
+};
+
 static inline int udp_v6_get_port(struct sock *sk, unsigned short snum)
 {
-	return udp_get_port(sk, snum, ipv6_rcv_saddr_equal);
+	return udp_get_port(sk, snum, &udp_ipv6_ops);
 }
 
 static struct sock *__udp6_lib_lookup(struct in6_addr *saddr, __be16 sport,
diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h
index 6e252f3..36b0c11 100644
--- a/net/ipv6/udp_impl.h
+++ b/net/ipv6/udp_impl.h
@@ -6,6 +6,8 @@
 #include <net/addrconf.h>
 #include <net/inet_common.h>
 
+extern const struct udp_get_port_ops udp_ipv6_ops;
+
 extern int  	__udp6_lib_rcv(struct sk_buff **, struct hlist_head [], int );
 extern void 	__udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *,
 			       int , int , int , __be32 , struct hlist_head []);
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c
index f54016a..c40a513 100644
--- a/net/ipv6/udplite.c
+++ b/net/ipv6/udplite.c
@@ -37,7 +37,7 @@
 
 static int udplite_v6_get_port(struct sock *sk, unsigned short snum)
 {
-	return udplite_get_port(sk, snum, ipv6_rcv_saddr_equal);
+	return udplite_get_port(sk, snum, &udp_ipv6_ops);
 }
 
 struct proto udplitev6_prot = {
diff --git a/net/irda/Kconfig b/net/irda/Kconfig
index 9efb17b..c8671a7 100644
--- a/net/irda/Kconfig
+++ b/net/irda/Kconfig
@@ -3,7 +3,7 @@
 #
 
 menuconfig IRDA
-	depends on NET
+	depends on NET && !S390
 	tristate "IrDA (infrared) subsystem support"
 	select CRC_CCITT
 	---help---
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 822917d..3e07e9d 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -17,6 +17,7 @@
  * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
  *    SSID)
  */
+#include <linux/delay.h>
 #include <linux/if_ether.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -27,7 +28,6 @@
 #include <linux/rtnetlink.h>
 #include <net/iw_handler.h>
 #include <asm/types.h>
-#include <asm/delay.h>
 
 #include <net/mac80211.h>
 #include "ieee80211_i.h"
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index e132c8a..e8b5c2d 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -299,7 +299,6 @@
 {
 	struct nf_conn *ct = (struct nf_conn *)nfct;
 	struct nf_conn_help *help = nfct_help(ct);
-	struct nf_conntrack_l3proto *l3proto;
 	struct nf_conntrack_l4proto *l4proto;
 	typeof(nf_conntrack_destroyed) destroyed;
 
@@ -317,10 +316,6 @@
 	 * destroy_conntrack() MUST NOT be called with a write lock
 	 * to nf_conntrack_lock!!! -HW */
 	rcu_read_lock();
-	l3proto = __nf_ct_l3proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num);
-	if (l3proto && l3proto->destroy)
-		l3proto->destroy(ct);
-
 	l4proto = __nf_ct_l4proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.l3num,
 				       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
 	if (l4proto && l4proto->destroy)
@@ -893,8 +888,13 @@
 	NF_CT_DUMP_TUPLE(newreply);
 
 	ct->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
-	if (!ct->master && help && help->expecting == 0)
-		help->helper = __nf_ct_helper_find(newreply);
+	if (!ct->master && help && help->expecting == 0) {
+		struct nf_conntrack_helper *helper;
+		helper = __nf_ct_helper_find(newreply);
+		if (helper)
+			memset(&help->help, 0, sizeof(help->help));
+		help->helper = helper;
+	}
 	write_unlock_bh(&nf_conntrack_lock);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index aa1a97ee..d6d39e2 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -830,11 +830,6 @@
 	char *helpname;
 	int err;
 
-	if (!help) {
-		/* FIXME: we need to reallocate and rehash */
-		return -EBUSY;
-	}
-
 	/* don't change helper of sibling connections */
 	if (ct->master)
 		return -EINVAL;
@@ -843,25 +838,34 @@
 	if (err < 0)
 		return err;
 
-	helper = __nf_conntrack_helper_find_byname(helpname);
-	if (!helper) {
-		if (!strcmp(helpname, ""))
-			helper = NULL;
-		else
-			return -EINVAL;
-	}
-
-	if (help->helper) {
-		if (!helper) {
+	if (!strcmp(helpname, "")) {
+		if (help && help->helper) {
 			/* we had a helper before ... */
 			nf_ct_remove_expectations(ct);
 			help->helper = NULL;
-		} else {
-			/* need to zero data of old helper */
-			memset(&help->help, 0, sizeof(help->help));
 		}
+
+		return 0;
 	}
 
+	if (!help) {
+		/* FIXME: we need to reallocate and rehash */
+		return -EBUSY;
+	}
+
+	helper = __nf_conntrack_helper_find_byname(helpname);
+	if (helper == NULL)
+		return -EINVAL;
+
+	if (help->helper == helper)
+		return 0;
+
+	if (help->helper)
+		/* we had a helper before ... */
+		nf_ct_remove_expectations(ct);
+
+	/* need to zero data of old helper */
+	memset(&help->help, 0, sizeof(help->help));
 	help->helper = helper;
 
 	return 0;
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c
index f4ea8fe..189ded5 100644
--- a/net/netfilter/xt_conntrack.c
+++ b/net/netfilter/xt_conntrack.c
@@ -134,12 +134,66 @@
 	nf_ct_l3proto_module_put(match->family);
 }
 
+#ifdef CONFIG_COMPAT
+struct compat_xt_conntrack_info
+{
+	compat_uint_t			statemask;
+	compat_uint_t			statusmask;
+	struct ip_conntrack_old_tuple	tuple[IP_CT_DIR_MAX];
+	struct in_addr			sipmsk[IP_CT_DIR_MAX];
+	struct in_addr			dipmsk[IP_CT_DIR_MAX];
+	compat_ulong_t			expires_min;
+	compat_ulong_t			expires_max;
+	u_int8_t			flags;
+	u_int8_t			invflags;
+};
+
+static void compat_from_user(void *dst, void *src)
+{
+	struct compat_xt_conntrack_info *cm = src;
+	struct xt_conntrack_info m = {
+		.statemask	= cm->statemask,
+		.statusmask	= cm->statusmask,
+		.expires_min	= cm->expires_min,
+		.expires_max	= cm->expires_max,
+		.flags		= cm->flags,
+		.invflags	= cm->invflags,
+	};
+	memcpy(m.tuple, cm->tuple, sizeof(m.tuple));
+	memcpy(m.sipmsk, cm->sipmsk, sizeof(m.sipmsk));
+	memcpy(m.dipmsk, cm->dipmsk, sizeof(m.dipmsk));
+	memcpy(dst, &m, sizeof(m));
+}
+
+static int compat_to_user(void __user *dst, void *src)
+{
+	struct xt_conntrack_info *m = src;
+	struct compat_xt_conntrack_info cm = {
+		.statemask	= m->statemask,
+		.statusmask	= m->statusmask,
+		.expires_min	= m->expires_min,
+		.expires_max	= m->expires_max,
+		.flags		= m->flags,
+		.invflags	= m->invflags,
+	};
+	memcpy(cm.tuple, m->tuple, sizeof(cm.tuple));
+	memcpy(cm.sipmsk, m->sipmsk, sizeof(cm.sipmsk));
+	memcpy(cm.dipmsk, m->dipmsk, sizeof(cm.dipmsk));
+	return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
+}
+#endif
+
 static struct xt_match conntrack_match = {
 	.name		= "conntrack",
 	.match		= match,
 	.checkentry	= checkentry,
 	.destroy	= destroy,
 	.matchsize	= sizeof(struct xt_conntrack_info),
+#ifdef CONFIG_COMPAT
+	.compatsize	= sizeof(struct compat_xt_conntrack_info),
+	.compat_from_user = compat_from_user,
+	.compat_to_user	= compat_to_user,
+#endif
 	.family		= AF_INET,
 	.me		= THIS_MODULE,
 };
diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c
index ce08b78..90fa107 100644
--- a/net/rxrpc/ar-peer.c
+++ b/net/rxrpc/ar-peer.c
@@ -59,14 +59,14 @@
 
 	ret = ip_route_output_key(&rt, &fl);
 	if (ret < 0) {
-		kleave(" [route err %d]", ret);
+		_leave(" [route err %d]", ret);
 		return;
 	}
 
 	peer->if_mtu = dst_mtu(&rt->u.dst);
 	dst_release(&rt->u.dst);
 
-	kleave(" [if_mtu %u]", peer->if_mtu);
+	_leave(" [if_mtu %u]", peer->if_mtu);
 }
 
 /*
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 3385ee5..f28bb2d 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -71,12 +71,9 @@
 
 
 /* Kick device.
-   Note, that this procedure can be called by a watchdog timer, so that
-   we do not check dev->tbusy flag here.
 
-   Returns:  0  - queue is empty.
-	    >0  - queue is not empty, but throttled.
-	    <0  - queue is not empty. Device is throttled, if dev->tbusy != 0.
+   Returns:  0  - queue is empty or throttled.
+	    >0  - queue is not empty.
 
    NOTE: Called under dev->queue_lock with locally disabled BH.
 */
@@ -115,7 +112,7 @@
 					kfree_skb(skb);
 					if (net_ratelimit())
 						printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
-					return -1;
+					goto out;
 				}
 				__get_cpu_var(netdev_rx_stat).cpu_collision++;
 				goto requeue;
@@ -135,10 +132,12 @@
 						netif_tx_unlock(dev);
 					}
 					spin_lock(&dev->queue_lock);
-					return -1;
+					q = dev->qdisc;
+					goto out;
 				}
 				if (ret == NETDEV_TX_LOCKED && nolock) {
 					spin_lock(&dev->queue_lock);
+					q = dev->qdisc;
 					goto collision;
 				}
 			}
@@ -163,26 +162,28 @@
 		 */
 
 requeue:
-		if (skb->next)
+		if (unlikely(q == &noop_qdisc))
+			kfree_skb(skb);
+		else if (skb->next)
 			dev->gso_skb = skb;
 		else
 			q->ops->requeue(skb, q);
 		netif_schedule(dev);
-		return 1;
+		return 0;
 	}
+
+out:
 	BUG_ON((int) q->q.qlen < 0);
 	return q->q.qlen;
 }
 
 void __qdisc_run(struct net_device *dev)
 {
-	if (unlikely(dev->qdisc == &noop_qdisc))
-		goto out;
+	do {
+		if (!qdisc_restart(dev))
+			break;
+	} while (!netif_queue_stopped(dev));
 
-	while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
-		/* NOTHING */;
-
-out:
 	clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
 }
 
@@ -544,6 +545,7 @@
 void dev_deactivate(struct net_device *dev)
 {
 	struct Qdisc *qdisc;
+	struct sk_buff *skb;
 
 	spin_lock_bh(&dev->queue_lock);
 	qdisc = dev->qdisc;
@@ -551,8 +553,12 @@
 
 	qdisc_reset(qdisc);
 
+	skb = dev->gso_skb;
+	dev->gso_skb = NULL;
 	spin_unlock_bh(&dev->queue_lock);
 
+	kfree_skb(skb);
+
 	dev_watchdog_down(dev);
 
 	/* Wait for outstanding dev_queue_xmit calls. */
@@ -561,11 +567,6 @@
 	/* Wait for outstanding qdisc_run calls. */
 	while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
 		yield();
-
-	if (dev->gso_skb) {
-		kfree_skb(dev->gso_skb);
-		dev->gso_skb = NULL;
-	}
 }
 
 void dev_init_scheduler(struct net_device *dev)
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index d24914d..f05ad9a 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -94,14 +94,13 @@
 	struct net_device *dev = sch->dev;
 	struct teql_sched_data *q = qdisc_priv(sch);
 
-	__skb_queue_tail(&q->q, skb);
-	if (q->q.qlen <= dev->tx_queue_len) {
+	if (q->q.qlen < dev->tx_queue_len) {
+		__skb_queue_tail(&q->q, skb);
 		sch->bstats.bytes += skb->len;
 		sch->bstats.packets++;
 		return 0;
 	}
 
-	__skb_unlink(skb, &q->q);
 	kfree_skb(skb);
 	sch->qstats.drops++;
 	return NET_XMIT_DROP;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 83a76ba..4dcdabf 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4164,6 +4164,7 @@
 	rwlock_t *addr_lock;
 	int err = 0;
 	void *addrs;
+	void *buf;
 	int bytes_copied = 0;
 
 	if (len != sizeof(struct sctp_getaddrs_old))
@@ -4217,13 +4218,14 @@
 		}
 	}
 
+	buf = addrs;
 	list_for_each(pos, &bp->address_list) {
 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		memcpy(&temp, &addr->a, sizeof(temp));
 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp);
 		addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len;
-		memcpy(addrs, &temp, addrlen);
-		to += addrlen;
+		memcpy(buf, &temp, addrlen);
+		buf += addrlen;
 		bytes_copied += addrlen;
 		cnt ++;
 		if (cnt >= getaddrs.addr_num) break;
@@ -4266,6 +4268,7 @@
 	size_t space_left;
 	int bytes_copied = 0;
 	void *addrs;
+	void *buf;
 
 	if (len <= sizeof(struct sctp_getaddrs))
 		return -EINVAL;
@@ -4316,6 +4319,7 @@
 		}
 	}
 
+	buf = addrs;
 	list_for_each(pos, &bp->address_list) {
 		addr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		memcpy(&temp, &addr->a, sizeof(temp));
@@ -4325,8 +4329,8 @@
 			err =  -ENOMEM; /*fixme: right error?*/
 			goto error;
 		}
-		memcpy(addrs, &temp, addrlen);
-		to += addrlen;
+		memcpy(buf, &temp, addrlen);
+		buf += addrlen;
 		bytes_copied += addrlen;
 		cnt ++;
 		space_left -= addrlen;
@@ -5227,7 +5231,12 @@
 	/* Allocate HMAC for generating cookie. */
 	if (sctp_hmac_alg) {
 		tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
-		if (!tfm) {
+		if (IS_ERR(tfm)) {
+			if (net_ratelimit()) {
+				printk(KERN_INFO
+				       "SCTP: failed to load transform for %s: %ld\n",
+					sctp_hmac_alg, PTR_ERR(tfm));
+			}
 			err = -ENOSYS;
 			goto out;
 		}
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 661ea2d..bfecb35 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -141,11 +141,6 @@
 	 * an ABORT, so we need to include it in the sac_info.
 	 */
 	if (chunk) {
-		/* sctp_inqu_pop() has allready pulled off the chunk
-		 * header.  We need to put it back temporarily
-		 */
-		skb_push(chunk->skb, sizeof(sctp_chunkhdr_t));
-
 		/* Copy the chunk data to a new skb and reserve enough
 		 * head room to use as notification.
 		 */
@@ -155,9 +150,6 @@
 		if (!skb)
 			goto fail;
 
-		/* put back the chunk header now that we have a copy */
-		skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
-
 		/* Embed the event fields inside the cloned skb.  */
 		event = sctp_skb2event(skb);
 		sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
@@ -168,7 +160,8 @@
 
 		/* Trim the buffer to the right length.  */
 		skb_trim(skb, sizeof(struct sctp_assoc_change) +
-			 ntohs(chunk->chunk_hdr->length));
+			 ntohs(chunk->chunk_hdr->length) -
+			 sizeof(sctp_chunkhdr_t));
 	} else {
 		event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
 				  MSG_NOTIFICATION, gfp);
diff --git a/sound/Kconfig b/sound/Kconfig
index 97532bb..9ea4738 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -2,6 +2,7 @@
 #
 
 menu "Sound"
+	depends on HAS_IOMEM
 
 config SOUND
 	tristate "Sound card support"